想象一下,我有一个扩展方法,它操作抽象对象的接口:
public static void BlowTheirWhoHoovers(this ICollection<Image> source)
{
...
}
此扩展程序知道如何吹嘘图像列表的人员。
注意:
Bitmap
,Metafile
,PngImage
),扩展程序就可以处理它source
列表可以通过任何类型的列表,只要它公开ICollection
source
列表可能会添加或删除项目,因此ICollection
而不是IEnumeration
(IEnumeration
不支持修改列表)这一切都很好,除了它不起作用,找不到扩展方法:
Collection<Bitmap> whoHonkers = new Collection<Bitmap>();
whoHonkers.BlowTheirWhoHoovers();
我认为这是失败的原因:
Collection
不会实现ICollection<T>
Bitmap
不属于Image
现在我可以更改我的扩展程序:
public static void BlowTheirWhoHoovers(this Collection<Bitmap> source)
{
...
}
做编译:
除了它不再有用(它需要Collection
,它需要Bitmap
),例如它无法处理除Collection<T>
之外的任何事情:
List<Bitmap> whoHonkers = new List<Bitmap>();
whoHonkers.BlowTheirWhoHoovers();
它也是Bitmap
:
List<Metafile> whoHonkers = new List<Metafile>();
whoHonkers.BlowTheirWhoHoovers();
或
List<PngImage> whoHonkers = new List<PngImage>();
whoHonkers.BlowTheirWhoHoovers();
如何将扩展程序应用于 :
的任何内容ICollection<Image>
我不能强迫任何人改变他们的声明,例如:
List<Bitmap>
到
Collection<Image>
更新:
解决方案探索的可能途径:
更新#2 :
我本可以简化ICollection
周围的一些干扰,并使其IEnumerable
(因为它是一个假设的例子,我可以弥补我想要的任何东西)。但屏幕截图已经显示Collection
,所以我将保留原样。
更新#3 :
作为foson pointed out,将其更改为IEnumerable
可以让方法欺骗答案。所以它绝对应该保持ICollection
。
答案 0 :(得分:1)
听起来像一个协变的问题。
如果您将签名更改为
public static void BlowTheirWhoHoovers(this IEnumerable<Image> source)
你应该能够在.NET 4(而非SL)中完成它。
有各种各样的问题是,如果你将ICollection<JpegImage>
传递给方法,那么该方法本身就不会知道它只能添加JpegImage
而不是Bitmap
s,从而失败类型安全。因此编译器不允许您这样做。 IEnumerable
的类型参数是covarient,如out
关键字所示,而ICollection
的类型参数不是(因为它在ICollection中都是返回位置和方法参数位置)接口)
public interface IEnumerable<out T>