创建Type 的通用列表并使用派生类填充它的解决方法?

时间:2021-01-06 17:02:38

I want to make a List and add derived classes to this list.

我想创建一个List并将派生类添加到此列表中。

I see here that this is not possible by design in .NET: http://msdn.microsoft.com/en-us/library/aa479859.aspx#fundamentals_topic12

我在这里看到这在.NET中的设计是不可能的:http://msdn.microsoft.com/en-us/library/aa479859.aspx#fundamentals_topic12

So what is the best practice solution to this? I guess I can box my derived classes to make them look like my superclass but that feels a little unwieldly. I suppose I should have designed my classes differently....but how?

那么最佳实践解决方案是什么?我想我可以将我的派生类打包,使它们看起来像我的超类,但感觉有点笨拙。我想我应该以不同的方式设计我的课程......但是如何?

3 个解决方案

#1


If I understand what you are trying to do, you should be able to do it just fine.

如果我明白你想要做什么,你应该能够做得很好。

List<SuperClass> myList = new List<SuperClass>();

SubClass item1 = new SubClass();
SuperClass item2 = new SuperClass();

myList.add(item1);
myList.add(item2);

This is valid code, and then you can easily retrieve the elements from the list, and use the basic rules of polymorphism for changing the types of the objects accordingly.

这是有效的代码,然后您可以轻松地从列表中检索元素,并使用多态的基本规则来相应地更改对象的类型。

#2


As Brian notes, this should work fine. The only common limitation people see in this area is covariance of lists as method arguments - i.e. they find that they can't pass a List<Dog> to a method that accepts a List<Animal>. The answer in that case is generics:

正如Brian所说,这应该可以正常工作。人们在这个领域看到的唯一常见限制是列表的协方差作为方法参数 - 即他们发现他们无法将List 传递给接受List 的方法。在这种情况下的答案是泛型:

public void Foo<T>(IList<T> list) where T : Animal {...}
....
List<Dog> dogs = ...
Foo(dogs); // implicit <Dog>

For more discussion on covariance (including the C# 4.0 changes that doesn't change the above scenario, see here).

有关协方差的更多讨论(包括不改变上述方案的C#4.0更改,请参见此处)。

#3


That would work fine. While you won't know the exact type of an item in the list (without casting) there are no problems with adding a derived type to a collection of base types.

那会很好。虽然您不知道列表中项目的确切类型(没有强制转换),但是将派生类型添加到基类型集合中没有问题。

What the article links to is the case where you try to use a collection of derived types as a collection of base types:

本文链接的是您尝试将派生类型集合用作基类型集合的情况:

void DisplayFruit(List<Fruit> fruit)
{
    fruit.ForEach(f => Console.WriteLine(f.ToString()));
}

List<Apples> apples = new List<Apples>();
// add apples here

DisplayFruit(apples); //Error!

If apples were declared as a List<Fruit> instead, it would work.

如果苹果被声明为List ,那么它将起作用。

#1


If I understand what you are trying to do, you should be able to do it just fine.

如果我明白你想要做什么,你应该能够做得很好。

List<SuperClass> myList = new List<SuperClass>();

SubClass item1 = new SubClass();
SuperClass item2 = new SuperClass();

myList.add(item1);
myList.add(item2);

This is valid code, and then you can easily retrieve the elements from the list, and use the basic rules of polymorphism for changing the types of the objects accordingly.

这是有效的代码,然后您可以轻松地从列表中检索元素,并使用多态的基本规则来相应地更改对象的类型。

#2


As Brian notes, this should work fine. The only common limitation people see in this area is covariance of lists as method arguments - i.e. they find that they can't pass a List<Dog> to a method that accepts a List<Animal>. The answer in that case is generics:

正如Brian所说,这应该可以正常工作。人们在这个领域看到的唯一常见限制是列表的协方差作为方法参数 - 即他们发现他们无法将List 传递给接受List 的方法。在这种情况下的答案是泛型:

public void Foo<T>(IList<T> list) where T : Animal {...}
....
List<Dog> dogs = ...
Foo(dogs); // implicit <Dog>

For more discussion on covariance (including the C# 4.0 changes that doesn't change the above scenario, see here).

有关协方差的更多讨论(包括不改变上述方案的C#4.0更改,请参见此处)。

#3


That would work fine. While you won't know the exact type of an item in the list (without casting) there are no problems with adding a derived type to a collection of base types.

那会很好。虽然您不知道列表中项目的确切类型(没有强制转换),但是将派生类型添加到基类型集合中没有问题。

What the article links to is the case where you try to use a collection of derived types as a collection of base types:

本文链接的是您尝试将派生类型集合用作基类型集合的情况:

void DisplayFruit(List<Fruit> fruit)
{
    fruit.ForEach(f => Console.WriteLine(f.ToString()));
}

List<Apples> apples = new List<Apples>();
// add apples here

DisplayFruit(apples); //Error!

If apples were declared as a List<Fruit> instead, it would work.

如果苹果被声明为List ,那么它将起作用。