使用基类一般为IEnumerable的< T>
我在一般情况下,继承和多态,接口等OOP很好地理解我遇到了一个奇怪的情况,我不明白为什么它不工作在所有...
I have a good understanding of OOP in general, inheritance and polymorphism, interfaces, etc. I encountered a strange situation and I don't understand why it does not work at all...
编辑:好吧,我发现,协方差(或逆变?)可以解决这个问题,但关键
EDIT : Ok, I found out that covariance (or contravariance?) may solve this problem, but crucially
我怎么能解决这个问题没有移动到C#4.0?
How can I solve this without moving to C# 4.0 ?
这里的情况。鉴于这两个类:
Here is the situation. Given these two classes :
public class CustomCollectionType<T> : IEnumerable<T>
{
/* Implementation here, not really important */
}
public class Entity : EntityBase
{
/* Implentation here, not important */
}
编译器会抱怨,当我尝试这个泛型方法
The compiler complains when I try to have this generic method
public void LoopThrough(IEnumerable<EntityBase> entityList)
{
foreach(EntityBase entity in entityList)
{
DoSomething(entity);
}
}
和尝试用这种方式:
CustomCollectionType<Entity> entityList;
/* Add items to list */
LoopThrough(entityList);
错误说我不能从 CustomCollectionType<转化;实体>
到的IEnumerable< EntityBase>
不过,我可以做到这一点:
However, I can do this :
public void Foo(EntityBase entity)
{
entity.DoSomething();
}
Foo(new Entity());
和这样的:
public void Bar(IEnumerable<Entity> entityList)
{ ... }
CustomCollectionType<Entity> entityList;
Bar(entityList);
为什么我不能创建我的方法与层次结构中的最高等级?类型显然兼容...我缺少的东西。
Why can't I create my method with the highest classes in the hierarchy? The types are obviously compatible... Am I missing something ?
编辑:?我想不会以任何方式改变现有的类来解决这个问题,因此创建一个新方法在任何一个类,或者实现额外的接口是出了问题。
EDIT : I want to solve this problem without altering the existing classes in any way, so creating a new method in any of the classes, or implementing an additional interface is out of the question.
让我们看看你的第一个案例。您有:
Let's consider your first case. You have:
class Bowl<T> : IEnumerable<T> {}
class Apple : Fruit {}
...
void LoopThrough(IEnumerable<Fruit> fruits) ...
和你打电话
Bowl<Apple> apples = whatever;
LoopThrough(apples);
这失败的C#3.0;它成功在C#4.0,因为的IEnumerable< T>
现在是在协变笔;苹果的序列,可作为水果的序列。
This fails in C# 3.0; it succeeds in C# 4.0 because IEnumerable<T>
is now covariant in T; a sequence of apples can be used as a sequence of fruits.
要使其在工作,C#3.0,你可以使用铸造$ C 。$ C>序列算
To make it work in C# 3.0 you can use the Cast
sequence operator.
Bowl<Apple> apples = whatever;
LoopThrough(apples.Cast<Fruit>());
要使其工作在C#2.0,实施播序列运营商自己的。它是代码只有几行
To make it work in C# 2.0, implement the Cast sequence operator yourself. It is only a couple lines of code.
请注意,在C#4.0中它仍然是不合法的说:
Note that in C# 4.0 it will still not be legal to say:
Bowl<Fruit> fruits = new Bowl<Apples>();
由于你当然可以说:
fruits.Add(new Orange());
和你只要把一个橘子放入碗中只能包含苹果。
and you just put an orange into a bowl that can only contain apples.