2017-06-17 77 views
1

我正在开发一个应用程序。为了论证的缘故,让我们说应用程序代表动物园。每个动物园中的数据被存储在一个List <Zoo>型变量,其中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>没有多大意义。在我的特定应用程序中,这种转换可能发生在许多列表中,每个列表包含大量项目(1000s),每个列表每秒多次,因此我不可能每次都进行转换。

对于上面的例子,组织类结构的最好方法是什么,以便完全避免这个问题?

+0

这_design_不_ “架构” _ – MickyD

+3

让'Zoo'通用?例如:'动物园其中T:动物'? – UnholySheep

+0

谢谢@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,MillipedeGoldfish)应该实现此接口,以便能够将其添加到Animals集合。但是,如果这样做,您只能在访问收藏时访问AnimalGroup属性。当然,这个接口可以包含你的对象所需要的其他东西。

希望这可以解释你的问题。

+1

AnimalGroupEnum与OP要求的任何内容有什么关系? – Enigmativity

+0

@Enigmativity它与他正在谈论的架构有关。为一个名为'GoldFish'的类添加'NumberOfLegs'会非常奇怪。我想给出一个可以为每种类型的对象所共有的东西的例子。另外,你的例子(因为我只能在这里发表评论)使得在同一个集合下收集所有东西有点困难。这是可能的,可以在这里看到:https://stackoverflow.com/questions/3215402/collection-of-generic-types –