2009-06-11 11 views
7

Diyelim ki Fruit (List<Fruit> fruits = new List<Fruit>()) genel bir listeye sahibim. Daha sonra (tümü Fruit'dan türetilmiş) bir nesneyi (Banana, Apple, Orange) ancak türetilmiş nesneler üzerinde farklı özellikler (Banana.IsYellow gibi) ekledim.Belirli bir türetilmiş nesneyi bir List <T> içinde nasıl edinebilirim?

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

Fakat Apple ve Orange nesneler üzerinde hiçbir IsYellow -property olmadığından bu geçerli değil tabii yürütülmesi sırasında:

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); 

Sonra bunu yapabilirsiniz.

List<Fruit>'dan sadece muz, elma, portakal vb. Nasıl alırım?

+0

C++ içinde bunu nasıl yapacağını bilen var mı? Bu ikilemde de sıkıştım ama kodumu C++ 'da yazıyorum! – Glolita

cevap

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

Vay, bunu bilmiyordum. Güzel! – Aistina

3

sadece

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

Şahsen ben bu yöntem daha okunabilir bulmak yapabilirdi:

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

Bununla birlikte, küçük bir performans isabeti ve esasen iki kez yaptığınız için unneccessairly vermemenizi söyleyen bir kod analizi uyarısı alacaksınız. – Ian

+1

Ahh, o zaman başka bir anti-desen varsa döngü, [looping case ifadesine kuzeni kapat]. Gözlerim kanadı. Buradaki örneğiniz yüzünden değil, ama bu şeyler sürdürülemez kanserlere dönüşüyor. –

+0

Yukarıdaki yorumlar anlamlıdır, ancak Ian'ın örneğinde boş çekmeyi engelleyen daha iyi bir şey var mı? Gözlerimin akmasını sağlayan kısım bu. – NascarEd

3

Adım 1: Önce Meyve listeden alt listesini yapmak gerekir. Alt listeyi yapmak için Generic'in FindAll() ve Predicate işlevini kullanın.

Adım 2: Daha sonra alt set sen yineleme yapabilirsiniz, sadece 'muz' İşte

olan kod

Step1 içerir: 2

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); 
} 

Adım: Burada,

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

Evet, bu işe yarayacak, ancak bunun kök bir UnitOfWork/Repository içeriği kullanıyorum, bu yüzden "meyve listesi" çok fazla nesne içerecek ve bunun bir kopyası bu bağlamda iyi bir fikir değil. . – antirysm

+1

Endişelenme.Alt liste gerçekten bir kopya değil, bunun yerine ana listede 'Banana'ya işaret eden işaretçileri tutuyor. Zaten) ( List .FindAll hakkında daha fazla bilgi için benim örnek kod aracılığıyla kontrol http://msdn.microsoft.com/en-us/library/fh1w7y8z.aspx bakın – Kaz

1

reklamı yüklemektedir. Başka bir sözdizimi ding, ancak .OfType < Muz>() muhtemelen en iyisidir.

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