使用基类一般为IEnumerable的< T> [英] Using base class as generic for IEnumerable<T>

查看:124
本文介绍了使用基类一般为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,你可以使用铸造序列算

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.

这篇关于使用基类一般为IEnumerable的&LT; T&GT;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆