bei typisierten Listen Basisklasse des Typs erstellen
-
Hallo,
ich bin letzte Woche mit C# angefangen und naja, irgendwie komme ich gerade nicht weiter, was typisierte Listen betrifft.
Ich habe folgendes:
class A {} class B : A {} .... List<B> bList; .... public void test(List<A> aList) { foreach (List<A> a in aList) {...} }
Prinzipiell also Klasse B erbt von A und meine Funktion soll eine Liste des Basistyps A akzeptieren. Geht aber nicht, der Compiler meckert immer er könne bList nicht in List<A> konvertieren, wenn ich test(bList) aufrufe. Warum nicht? Und wie kriege ich das gelöst?
Vielen Dank.
-
Das geht ganz einfach nicht weil List< A > und List< B > komplett unterschiedliche Typen sind.
-
Und wie würde ich sowas dann lösen?
-
Ein CopyTo oder ConvertTo Funktion schreiben.
-
Oder generisch arbeiten:
public void Test<T>(List<T> list) where T : A { foreach (A item in list) { } }
-
Oder aus List<B> bList einfach List<A> bList machen!
-
Hallo,
hier ein kleines Beispiel zur Veranschaulichung:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DerivedClassInGenericList { class Program { static void Main(string[] args) { Test(); Console.WriteLine("\nHIT ENTER TO EXIT."); Console.ReadLine(); } public static void Test() { List<A> lst = new List<A>(); Console.WriteLine("Adding one B-object to the list."); lst.Add(new B()); Console.WriteLine("Adding one A-object to the list."); lst.Add(new A()); Console.WriteLine("\nListing items by casting all list items to the base class (A):"); foreach (A item in lst) Console.WriteLine(item.Name); try { Console.WriteLine("\nListing items by casting all items to the derived class (B):"); foreach (B item in lst) Console.WriteLine((item as A).Name); } catch (InvalidCastException ex) { Console.WriteLine("Ooops...\nYou can cast a derived class (B) to a base class (A).\nBut you cannot cast the base class (A) to a class derived from it (B)."); } Console.WriteLine("\nListing anyway. Everything is an object:"); foreach (object item in lst) if (item is A) Console.WriteLine((item as A).Name); else if (item is B) Console.WriteLine((item as B).Name); } } public class A { public virtual string Name { get { return "A"; } } } public class B : A { public override string Name { get { return "B"; }} } }
-
Dieses Stück Code ist total überflüssig!
else if (item is B) Console.WriteLine((item as B).Name);
Möglich wäre auch gewesen:
public void test(IEnumerable aList)
-
David_pb schrieb:
Dieses Stück Code ist total überflüssig!
So ist es. Zumindest so lange man mit der abgeleiteten Klasse nichts spezifisches vor hat...
-
maro158 schrieb:
David_pb schrieb:
Dieses Stück Code ist total überflüssig!
So ist es. Zumindest so lange man mit der abgeleiteten Klasse nichts spezifisches vor hat...
Selbst in diesem Fall würde der else-Zweig nie erreicht werden.
-
David_pb schrieb:
Selbst in diesem Fall würde der else-Zweig nie erreicht werden.
Und schon wieder hast Du recht. Also, ich korrigiere:
if (item is B) Console.WriteLine((item as B).Age); else if (item is A) Console.WriteLine((item as A).Name);
Nun, das meinte ich.
-
Anmerkung: Man kann übrigens auch auf einen konkreten Typen testen.
if (item.GetType() == typeof( B ) ) Console.WriteLine((item as B).Age); else if (item.GetType() == typeof( A ) ) Console.WriteLine((item as A).Name);
-
bool b = item.GetType() == typeof( B );
ist daselbe wie
bool b = item is B;
-
simon.gysi schrieb:
bool b = item.GetType() == typeof( B );
ist daselbe wie
bool b = item is B;
Durchaus nicht:
class A { } class B : A { } class C : B { } class Program { static void Main(string[] args) { A x = new C(); Test1( x ); Test2( x ); Console.ReadKey(); } static void Test1( object x ) { if ( x is A ) Console.WriteLine( "is A" ); if ( x is B ) Console.WriteLine( "is B" ); if ( x is C ) Console.WriteLine( "is C" ); } static void Test2( object x ) { if ( x.GetType() == typeof( A ) ) Console.WriteLine( "_is_ A" ); if ( x.GetType() == typeof( B ) ) Console.WriteLine( "_is_ B" ); if ( x.GetType() == typeof( C ) ) Console.WriteLine( "_is_ C" ); } }
-
100% acknowledge.
-
David_pb schrieb:
Durchaus nicht
Ein Blick hinter die Kulissen:
// if (item.GetType() == typeof(B)) IL_0107: ldloc.s V_6 IL_0109: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType() IL_010e: ldtoken DerivedClassInGenericList.B IL_0113: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) IL_0118: ceq
// if (item is B) IL_0107: ldloc.s V_6 IL_0109: [b]isinst[/b] DerivedClassInGenericList.B IL_010e: ldnull IL_010f: cgt.un
Wie man im letzten IL-Codeblock sieht, wird im Fall von if (item is
einfach isinst aufgerufen. Isinst übeprüft ob die auf dem Stack abgelegte Referenz vom Typ DerivedClassInGenericList.B ODER ein von DerivedClassInGenericList.B abgeleiteter Typ ist.
-
Genau so ist das!
-
Ohje!
Ich denke die generische Definition ist hier die beste Lösung für mich
Ich werd das mal probieren.
Danke euch allen!