2009-06-11 4 views
7

Nehmen wir an, ich habe eine generische Liste von Fruit(). Ich füge dann ein paar Objekte (alle abgeleitet von Fruit) - , Apple, Orange aber mit unterschiedlichen Eigenschaften auf den abgeleiteten Objekten (wie Banana.IsYellow).Wie bekomme ich ein bestimmtes abgeleitetes Objekt in einer Liste <T>?

List<Fruit> fruits = new List<Fruit>(); 
Banana banana1 = new Banana(); 
Banana banana2 = new Banana(); 
Apple apple1 = new Apple(); 
Orange orange2 = new Orange(); 

fruits.Add(banana1); 
fruits.Add(banana2); 
fruits.Add(apple1); 
fruits.Add(orange1); 

Dann kann ich dies tun:

foreach(Banana banana in fruits) 
    Console.Write(banana.IsYellow); 

Aber zur Ausführungszeit natürlich nicht gültig ist, weil es keine IsYellow -property auf den Apfel und Orange Objekte ist.

Wie bekomme ich nur die Bananen, Äpfel, Orangen usw. aus der List<Fruit>?

+0

Weiß jemand, wie man das in C++ macht ?? Ich stecke auch in diesem Dilemma, aber ich schreibe meinen Code in C++! – Glolita

Antwort

31
foreach(Banana b in fruits.OfType<Banana>()) 
+0

Wow, das wusste ich nicht. Nett! – Aistina

3

Sie könnten nur tun

foreach(Fruit fruit in fruits) 
{ 
    Banana b = fruit as Banana; 
    if(b != null) 
    { 
     Console.Write(b.IsYellow); 
    } 
} 
1

Ich persönlich finde diese Methode besser lesbar:

foreach(Fruit fruit in fruits) 
{ 
    if (fruit is Banana) 
    { 
     Banana b = fruit as Banana; 
     Console.Write(b.IsYellow); 
    } 
    else if (fruit is Apple) 
    { 
     // ... 
    } 
} 
+0

Sie erhalten jedoch einen leichten Leistungseinbruch und eine Warnung zur Codeanalyse, in der Sie darauf hingewiesen werden, dass Sie nicht unnötigerweise casten müssen, weil Sie es im Wesentlichen zweimal tun. – Ian

+1

Ahh, die Schleife, wenn dann sonst anti-Muster [schließen Cousin der Looping Case-Anweisung]. Meine Augen bluten. Nicht wegen Ihres Beispiels, aber diese Dinge wachsen zu unhaltbaren Krebsarten. –

+0

Die obigen Kommentare sind sinnvoll, aber gibt es etwas Besseres, das den Null-Check in Ians Beispiel vermeidet. Das ist der Teil, der MEINE Augen bluten lässt. – NascarEd

3

Schritt 1: Zuerst sollten Sie Unterliste aus Obst Liste. Um die Unterliste zu verwenden, verwenden Sie die Funktionen FindAll() und Predicate von Generic.

Schritt 2: Später in der Untergruppe Sie laufen kann, die nur

Hier Banana 'enthält den Code

Schritt 1:

List<Fruit> fruits = new List<Fruit>(); 
Banana banana1 = new Banana(); 
Banana banana2 = new Banana(); 
Apple apple1 = new Apple(); 
Orange orange1 = new Orange(); 

fruits.Add(banana1); 
fruits.Add(banana2); 
fruits.Add(apple1); 
fruits.Add(orange1); 

//Extract Banana from fruit list 
List<Fruit> bananaComb = fruits.FindAll(IsBanana); 

//Now iterate without worring about which fruit it is 
foreach (Fruit fruit in bananaComb) 
{ 
    Console.WriteLine(((Banana)fruit).IsYellow); 
} 

Schritt 2: Hier kommt die Prädikatfunktion

//A Predicate function to determine whether its a Banana 
static protected bool IsBanana(Fruit aFruit) 
{ 
    return aFruit.GetType().Name == "Banana" ? true : false; 
} 
+0

Ja, das würde funktionieren, aber ich benutze dies ist ein Root UnitOfWork/Repository-Kontext, so dass die "Liste der Früchte" wird eine Menge von Objekten enthalten, so dass eine Kopie davon ist keine gute Idee in diesem Zusammenhang . – antirysm

+1

Mach dir keine Sorgen.Die Unterliste ist nicht wirklich eine Kopie, sondern enthält nur die Zeiger, die auf 'Banana' in der Hauptliste zeigen. prüfe ich schon durch meinen Beispielcode Um mehr über Liste .FindAll Klammer() wissen http://msdn.microsoft.com/en-us/library/fh1w7y8z.aspx – Kaz

1

ad ding eine andere Syntax, obwohl .OfType < Banana>() ist wahrscheinlich die beste.

foreach (Banana b in fruits.Where(x => x is Banana))