使用基类作为IEnumerable 的通用
我对OOP一般,inheritance和多态,接口等有很好的理解。我遇到了一个奇怪的情况,我不明白为什么它根本不起作用…
编辑:好的,我发现协方差(或逆变?)可以解决这个问题,但至关重要
我们还在使用.NET 2.0
如何在不转向C#4.0的情况下解决这个问题?
这是情况。 鉴于这两个类:
public class CustomCollectionType : IEnumerable { /* Implementation here, not really important */ } public class Entity : EntityBase { /* Implentation here, not important */ }
当我尝试使用这种通用方法时,编译器会抱怨
public void LoopThrough(IEnumerable entityList) { foreach(EntityBase entity in entityList) { DoSomething(entity); } }
并尝试以这种方式使用它:
CustomCollectionType entityList; /* Add items to list */ LoopThrough(entityList);
错误说我无法从CustomCollectionType
转换为IEnumerable
。
但是,我可以这样做:
public void Foo(EntityBase entity) { entity.DoSomething(); } Foo(new Entity());
还有这个 :
public void Bar(IEnumerable entityList) { ... } CustomCollectionType entityList; Bar(entityList);
为什么我不能用层次结构中最高的类创建我的方法? 这些类型显然是兼容的…我错过了什么?
编辑:我想解决这个问题,而不用任何方式改变现有的类,所以在任何类中创建一个新方法,或实现一个额外的接口是不可能的。
让我们考虑你的第一个案例。 你有:
class Bowl : IEnumerable {} class Apple : Fruit {} ... void LoopThrough(IEnumerable fruits) ...
你打电话
Bowl apples = whatever; LoopThrough(apples);
这在C#3.0中失败了; 它在C#4.0中取得成功,因为IEnumerable
现在在T中是协变的; 一系列苹果可以用作一系列水果。
要使它在C#3.0中工作,您可以使用Cast
序列运算符。
Bowl apples = whatever; LoopThrough(apples.Cast());
要使它在C#2.0中工作,请自己实现Cast序列运算符 。 它只有几行代码。
请注意,在C#4.0中,说:
Bowl fruits = new Bowl();
因为你当然可以说:
fruits.Add(new Orange());
你只需将橙子放入一个只能装苹果的碗里。
是的,.NET可能会有点烦人,因为它无法一次性投射所有通用参数。 相反,也许尝试这样的通用方法来缓解问题。
public void LoopThrough(IEnumerable entityList) where T : EntityBase { foreach(T entity in entityList) { DoSomething(entity as EntityBase); } }
这些类型兼容但有点不兼容,这里的主要原因是你在参数中使用基类型作为IEnumerable而不是实际类型,尽管实体的基础是实体库,因为类型参数和约束的规则对generics类行为有几个含义,特别是关于inheritance和成员可访问性
generics类是不变的。 换句话说,如果输入参数指定了List
那么如果尝试提供List
List
则会出现编译时错误。
这就是为什么你得到那个错误,就像在你的最后一样,例如T是相同的。
但是,如果您使用接口,它将完全正常工作,因为所有接口都是兼容的
public class Entity : IEntityBase { /* Implentation here, not important */ } public void LoopThrough(IEnumerable entityList) { foreach(IEntityBase entity in entityList) { DoSomething(entity); } }
而且你的方法会很好
CustomCollectionType entityList; LoopThrough(entityList);
因为entitylist有一种IEntityBase
你可以尝试的另一件事是typeof(获取类型)或使用强制转换,它应该工作
我可能会遗漏一些东西,但如果你的CustomCollectionType的意图应该是一个实体基础但允许使用IEnumerable,那么你不应该首先将IT作为实体库的基础吗? 如…
public class CustomCollectionType : EntityBase, IEnumerable { /* Implementation here, not really important */ }
然后你的LoopThrough应该工作,因为自定义集合类型是从EntityBase派生出来的,并且有任何预期的方法,属性等可用…或者最坏的情况,你可以在调用函数时输入它,如
上述就是C#学习教程:使用基类作为IEnumerable 的通用分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
Bowl apples = whatever; LoopThrough((EntityBase)apples);
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1004341.html