如何将通用扩展应用于特定的泛型类型?

时间:2011-12-28 16:15:00

标签: visual-studio-2010 extension-methods

想象一下,我有一个扩展方法,它操作抽象对象的接口:

public static void BlowTheirWhoHoovers(this ICollection<Image> source)
{
   ...
}

此扩展程序知道如何吹嘘图像列表的人员。

注意

  • 这是图片的列表,它是抽象的。只要列表包含来自图片的任何内容(例如BitmapMetafilePngImage),扩展程序就可以处理它
  • source列表可以通过任何类型的列表,只要它公开ICollection
  • 由于source列表可能会添加或删除项目,因此ICollection而不是IEnumerationIEnumeration不支持修改列表)

这一切都很好,除了它不起作用,找不到扩展方法:

Collection<Bitmap> whoHonkers = new Collection<Bitmap>();
whoHonkers.BlowTheirWhoHoovers();

enter image description here

我认为这是失败的原因:

  • Visual Studio认为Collection不会实现ICollection<T>
  • Visual Studio认为Bitmap不属于Image

现在我可以更改我的扩展程序:

public static void BlowTheirWhoHoovers(this Collection<Bitmap> source)
{
   ...
}
编译:

enter image description here

除了它不再有用(它需要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

1 个答案:

答案 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>

http://msdn.microsoft.com/en-us/library/dd799517.aspx