对接口使用泛型集合
本文关键字:泛型 集合 接口 | 更新日期: 2023-09-27 18:19:07
我正在使用c# 5/。. NET 4.5 in Visual Studio 2013 Pro on Windows 7.
我想使用项目集合,其中唯一的要求是项目实现特定的接口。集合中的项不一定是共同继承树的一部分(即集合不会基于共同的祖先),它们可以是任意的类,但都将实现指定的接口(因此目标是将集合基于它们都实现的公共接口)。
我在这方面有麻烦。如果我有一个项的集合,它实现了我想要的接口,我就不能把这个集合传递给一个需要基于该接口的集合的方法。
这里有一些代码使它更具体。
using System.Collections.Generic;
class Test
{
public interface IDrawable
{
void Draw();
}
public class Shape : IDrawable
{
public void Draw() {}
}
public void DrawItems(List<IDrawable> itemsToDraw) {}
public Test()
{
List<Shape> shapes = new List<Shape>();
DrawItems(shapes);
}
}
调用drawwitems会生成一个编译错误。该方法期望一个实现IDrawable的项目集合。我传入一个Shape对象集合。因为Shape对象确实实现了可绘制的,我希望我能摆脱这个。
看起来这不会工作,但我试图理解为什么。我查找了有关协方差和逆变的信息,但没有找到任何专门针对这种情况的信息。
关于为什么这不起作用有什么想法或信息吗?
这是一个非常常见的问题。
正如你注意到的,你想要的特征被称为协方差;在这个网站上搜索一下,你会发现很多类似的问题。
列表不是协变的,因为它们不能安全地协变。你有一碗苹果,你想把它当作一碗水果,但是你可以把香蕉放进一碗水果里,但是你不能把香蕉放进一碗苹果里。因此,你不能把一碗苹果当作一碗水果。这里也是一样。形状列表不能用作可绘制对象列表,因为你可以将非形状放入可绘制对象列表中。
IEnumerable<T>
在c# 4中是协变的,如果T是引用类型。如果你需要协方差,你应该传递序列而不是列表。List<Shape>
可以转化为IEnumerable<IDrawable>
,因为无法使用IEnumerable<IDrawable>
将非形状添加到列表中。
如果你想了解c#中协方差和逆变的更多信息,请咨询我的MSDN博客:
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance +和+抗变性/
从底部开始;