2017-06-17 13 views
1

私はアプリケーションを開発しています。議論のために、アプリケーションが動物園を表すとしましょう。各動物園のためのデータとして定義されるZooList <Zoo>型変数に格納されている:デザインをリストに変換することを避ける<Derived>をリストに追加<Base>

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

Animalは、次のように定義される。

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

    ... 
} 

そして種々のクラスが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"; 
    } 
    ... 
} 

私たちが狂った世界に住んでいるとしましょう。ここでそれぞれZooにはAnimal(ただし、希望する数はAnimal)一つの特定のZooは本当にMillipedesが好き:

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

Zooが本当に金魚好き:理論的には

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

Animalクラスは何もすることができ、そして、私は別の実装がどのように見えるかを知る方法はありません特定のZooクラスになります。理想的には、List<Dog>またはList<Millipede>で作業したいと思います。List<Animal>ではなく、Animalサブクラスの特定のプロパティ/メソッドにアクセスできます。私はConvert List<DerivedClass> to List<BaseClass>に出くわしました。これにはいくつかのオプションがあり、List<Animal>からList<Dog>へのキャストはあまり意味がありません。私の特定のアプリケーションでは、この変換は、リストごとに1秒間に複数回、(1000秒ごとに)多数の項目を持つ多くのリストで発生する可能性があります。そのため、毎回変換を実行することは現実的ではありません。

上記の例のように、この問題を完全に回避できるように、クラス構造を整理する最良の方法は何ですか?

+0

をそれは_design_ない_ "アーキテクチャ" _ – MickyD

+3

'Zoo'は一般的なmakeの?例: 'Zoo T:Animal'? – UnholySheep

+0

Thanks @MickyD、タイトルが更新されました。 –

答えて

2

これは何が必要でしょうです:

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

は今、あなたはこれを行うことができます:

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

ありがとうございます!これは確かに私の問題をかなりうまく解決します。 –

-1

私はあなたの最善の策は、作業を計画しているすべてのタイプのオブジェクトの共通の動作を追跡することだと思います。これは、あなたの例に基づいて、動物のコレクションの場合はかなり簡単かもしれませんが、オブジェクトが非常に異なる場合(車、コンピュータ周辺機器、建築材料、食品)、ほとんど不可能です。

の動作でに類似点がある場合は、使用するすべてのオブジェクトによって実装される一般的なインターフェイスを使用することをお勧めします。インタフェースとともに

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

あなたの例に基づいて、あなたはこのような何かを追加でき

public interface IAnimal 
{ 
    AnimalGroupEnum AnimalGroup { get; } 
} 

を次に、あなたのZooクラスには、次のようになります。

public class Zoo 
{ 
    List<IAnimal> Animals 
} 

そして、すべての動物を定義した(Dog,MillipedeまたはGoldfish)は、このインターフェイスを実装して、Animalsコレクションに追加できるようにする必要があります。しかし、これを行うと、あなたはコレクションの上に行くときにAnimalGroupプロパティにアクセスするだけです。もちろん、このインタフェースにはオブジェクトから必要なものが含まれている可能性があります。

これはあなたの質問を少し明るくすることを望みます。

+1

'AnimalGroupEnumはOPが尋ねたものと何が関係していますか? – Enigmativity

+0

@Enigmativityそれは彼が話しているアーキテクチャと関係があります。 'GoldFish'というクラスに' NumberOfLegs'を追加するのはかなり奇妙なことでした。私は、オブジェクトの種類ごとに共通化できるものの例を挙げたいと思っていました。また、あなたの例(ここでしかコメントできないので)は、同じコレクションの下のすべてを少し難しくすることになります。 https://stackoverflow.com/questions/3215402/collection-of-generic-types –

関連する問題