2010-01-15 12 views
5

Questo può sembrare un tipo di "lavoro a casa" e/o banale, ma è per un vero scopo aziendale; è solo il modo più semplice a cui potrei pensare per spiegare ciò che sto tentando concettualmente di fare.Identificazione dei tipi derivati ​​da un elenco di oggetti della classe base

Supponiamo che io abbia una classe Animale e alcune altre classi (Uccello, Gatto, Canguro). Ognuno di questi eredita da Animal.

degli animali potrebbe essere simile a questo:

public class Animal 
{ 
    public Animal() 
    { 

    } 

    public string Name { get; set; } 
    public string AnimalType { get; set; } 
    public List<Animal> Friends { get; set; } 
} 

Kangaroo potrebbe essere simile a questo:

public class Kangaroo : Animal 
{ 
    public Kangaroo() 
    { 

    } 

    public int TailLengthInches { get; set; } 
} 

Supponiamo che il canguro ha due amici, un uccello e un gatto. Come potrei aggiungerli alla lista di amici "Animali" (come tipo Animale), ma preservare la possibilità di accedere alle proprietà delle classi derivate? (come in, devo ancora essere in grado di lavorare con proprietà specifiche per il tipo di animale, ad esempio FeatherColor per l'uccello, anche se saranno considerati solo "animali"

Il motivo I sto provando a farlo quando più tardi avrò la lista degli "amici" dell'animale, è fondamentale che io sappia che tipo di animale è l'amico, a seconda del tipo di animale (che sia un uccello, un gatto, ecc.) Voglio fare qualcosa di diverso (mostrare un modello diverso in una pagina ASP.NET, in realtà, ma non ho bisogno di aiuto con quello specifico)

Immagino che si riduce a questo ... se ho una lista di Animali, come faccio a sapere qual è il tipo derivato per ciascuno degli oggetti nella lista, così posso ricondurli al loro tipo derivato o fare qualcos'altro a mi consente di ottenere le proprietà specifiche e diverse che sono su ciascun tipo derivato?

Grazie!

+1

Suggerimento: per ottenere il codice per visualizzare correttamente, utilizzare il pulsante 101010 nell'editor (o trattino da quattro spazi) . – itowlson

risposta

7

È possibile utilizzare LINQ per filtrare il tipo che stai cercando

animals.Friends = new List<Animal> { new Kangaroo(), new Bird() }; 
foreach (var kangaroo in animals.Friends.OfType<Kangaroo>()) { 
    kangaroo.Hop(); 
} 
+0

Questo è un modo davvero elegante di gestirlo. Grazie! –

1

Prova a trasmettere è:

var friendBird = friend as Bird; 
if (friendBird != null) 
{ 
    // It's a bird, so do something with it 
) 
+0

+1 per usare la parola chiave 'as' per evitare il doppio casting implicato con la parola chiave' is' e quindi lanciare l'oggetto. –

1

È possibile utilizzare typeof per ottenere il tipo effettivo, o utilizzare i is o as operatori per testare ed eventualmente lanciare:

foreach (Animal a in Friends) 
{ 
    Kangaroo k = a as Kangaroo; 
    if (a != null) 
    { 
    // it's a kangaroo 
    k.JumpAround(); 
    } 
    Ostrich o = a as Ostrich; 
    if (o != null) 
    { 
    o.StickHeadInSand(); 
    } 
} 

(non ho usate le clausole else qui, che potrebbero causare errori se state provando contro tipi che potrebbero essere in una gerarchia, ad esempio se avete entrambe le clausole di Kangaroo e Marsupial, probabilmente NON volete che entrambe siano eseguite!)

si può anche fare questo con il is dell'operatore, che sembra più bello, ma farà FxCop grido:

foreach (Animal a in Friends) 
{ 
    if (a is Kangaroo) 
    { 
    ((Kangaroo)a).JumpAround(); 
    } 
} 

In generale, tra l'altro, probabilmente si vuole cercare l'opportunità di mettere un metodo virtuale su Animal e implementare tale metodo in modo polimorfico, piuttosto che avere istruzioni if-monster che risultino in un fragile accoppiamento con un insieme specifico di classi derivate.

0

Utilizzare la parola chiave 'è'.

se (animale è uccello) ...

0
animals.Friends = new List<Animal> { new Kangaroo(), new Bird() }; 
foreach (Animal animal in animals.Friends) 
{ 
if (animal is Kangaroo) 
Console.WriteLine("Kangaroo"); 
else if (animal is Bird) 
Console.WriteLine("Bird"); 
} 
Problemi correlati