2017-06-17 2 views
1

Ich entwickle eine Anwendung. Um der Sache willen sagen wir, dass die Anwendung Zoo (s) darstellt. Die Daten für jeden Zoo befindet sich in einem List <Zoo> Typ Variable gespeichert, wo Zoo ist wie folgt definiert:Design Vermeiden von Konvertieren von Liste <Derived> zu Liste <Base>

public class Zoo { 
    List<Animal> animals; 
    ... 
} 

Animal ist definiert als:

public abstract class Animal { 
    public virtual string Name {get; set;}; 

    ... 
} 

Und verschiedene Klassen stammen aus Animal:

public class Dog { 
    public int nLegs = 4; 
    public string furColour= "White"; 
    public Dog() { 
     Name = "Dog"; 
    } 
    ... 
} 

public class Millipede { 
    public int nLegs = int.maxValue; 
    public Millipede() { 
     Name = "Millipede"; 
    } 
    ... 
} 

public class Goldfish { 
    public string colour = "Red"; 
    public Goldfish() { 
     Name = "Goldfish"; 
    } 
    ... 
} 

Sagen wir, wir leben in einer verrückten Welt, in der jeder Zoo nur einen Typ haben kann Animal (aber so viele verschiedene Instanzen von Animal, wie sie wollen). Eine besondere Zoo mag wirklich Millipedes:

List<Animal>.Add(new Millipede()); 
List<Animal>.Add(new Millipede()); 
List<Animal>.Add(new Millipede()); 
List<Animal>.Add(new Millipede()); 

Ein weiterer Zoo wirklich mag Goldfish:

List<Animal>.Add(new Goldfish()); 
List<Animal>.Add(new Goldfish()); 
List<Animal>.Add(new Goldfish()); 
List<Animal>.Add(new Goldfish()); 

In der Theorie der Animal Klasse kann alles sein, und ich habe keine Möglichkeit zu wissen, was verschiedene Implementierungen aussehen wird , aber die spezifische Zoo Klasse wird. Idealerweise würde ich gerne mit List<Dog> oder List<Millipede> arbeiten und nicht mit List<Animal>, damit ich auf bestimmte Eigenschaften/Methoden der Animal Unterklasse zugreifen kann. Ich bin auf Convert List<DerivedClass> to List<BaseClass> gestoßen, die ein paar Optionen auflistet und beschreibt, warum zu List<Dog> Casting nicht viel Sinn macht. In meiner speziellen Anwendung könnte diese Konvertierung für viele Listen mit einer großen Anzahl von Elementen (1000s), mehrmals pro Sekunde pro Liste stattfinden, so dass es für mich nicht machbar ist, jedes Mal eine Konvertierung durchzuführen.

Für ein Beispiel wie oben, was ist der beste Weg, um die Klassenstruktur zu organisieren, so dass dieses Problem insgesamt vermieden werden kann?

+0

Es ist _design_ nicht _ "Architektur" _ – MickyD

+3

Make 'Zoo' Generika? z.B .: 'Zoo wo T: Tier'? – UnholySheep

+0

Danke @MickyD, Titel aktualisiert. –

Antwort

2

ist wahrscheinlich das, was Sie brauchen:

public class Zoo<T> where T : Animal 
{ 
    public List<T> animals = new List<T>(); 
} 

public abstract class Animal 
{ 
    public virtual string Name {get; set;} 
} 

public class Dog : Animal 
{ 
    public int nLegs = 4; 
    public string furColour= "White"; 
    public Dog() 
    { 
     Name = "Dog"; 
    } 
} 

public class Millipede : Animal 
{ 
    public int nLegs = int.MaxValue; 
    public Millipede() 
    { 
     Name = "Millipede"; 
    } 
} 

public class Goldfish : Animal 
{ 
    public string colour = "Red"; 
    public Goldfish() 
    { 
     Name = "Goldfish"; 
    } 
} 

Jetzt können Sie dies tun:

var zoo = new Zoo<Dog>(); 
zoo.animals.Add(new Dog()); 
zoo.animals.Add(new Dog()); 
zoo.animals.Add(new Dog()); 
+0

Vielen Dank! Das löst mein Problem ganz gut. –

-1

Ich denke, Ihre beste Wette wäre, zu versuchen, das allgemeine Verhalten aller Arten von Objekten aufzuspüren, mit denen Sie arbeiten möchten. Dies ist im Falle einer Tiersammlung (anhand Ihres Beispiels) ziemlich einfach, aber fast unmöglich, wenn sich die Objekte sehr stark voneinander unterscheiden (Autos, Computerperipherie, Baumaterialien und Lebensmittel).

Wenn Sie es schaffen, Ähnlichkeiten in Verhalten zwischen ihnen zu finden, dann Ihre beste Wette wäre die Verwendung einer allgemeinen Schnittstelle, die von jedem Objekt implementiert werden sollte, die Sie planen zu verwenden.

public enum AnimalGroupEnum 
{ 
    Amphibian, 
    Bird, 
    Fish, 
    Invertebrate, 
    Mammal, 
    Reptile, 
} 

Zusammen mit einer Schnittstelle:

public interface IAnimal 
{ 
    AnimalGroupEnum AnimalGroup { get; } 
} 

Dann wird Ihre Zoo Klasse wird:

public class Zoo 
{ 
    List<IAnimal> Animals 
} 

Und alle

Basierend auf Ihrem Beispiel könnten Sie so etwas wie diese hinzufügen Tiere definiert (Dog, Millipede oder Goldfish) sollte diese Schnittstelle implementieren, um es der Animals Sammlung hinzufügen zu können. Aber wenn Sie dies tun, haben Sie nur Zugriff auf die AnimalGroup Eigenschaft, wenn Sie über die Sammlung gehen. Natürlich könnte diese Schnittstelle andere Dinge enthalten, die Sie von Ihren Objekten benötigen.

Hoffentlich bringt dies etwas Licht auf Ihre Frage. Diese

+1

Was hat 'AnimalGroupEnum' mit irgendetwas zu tun, das das OP verlangt? – Enigmativity

+0

@Enigmatismus Es hat etwas mit der Architektur zu tun, von der er spricht. Es wäre ziemlich seltsam gewesen, 'NumberOfLegs' für eine Klasse namens' GoldFish' hinzuzufügen. Ich wollte ein Beispiel geben für etwas, das für jede Art von Objekt gemeinsam gemacht werden kann. Auch Ihr Beispiel (da ich hier nur kommentieren kann) macht es etwas schwierig, alles unter der gleichen Sammlung zu sammeln. Es ist möglich, wie hier zu sehen ist: https://stackoverflow.com/questions/3215402/collection-of-generic-types –

Verwandte Themen