Imagine i have an extension method that operates of an interface of abstract objects:
public static void BlowTheirWhoHoovers(this ICollection<Image> source)
{
...
}
This extension knows how to blow the who hoovers of a list of images.
Note:
- it’s a list of Images, which is abstract. As long as the lists contain anything that descends from Image (e.g.
Bitmap,Metafile,PngImage) the extension can handle it sourcelist can by any kind of list as long as it exposesICollection- since
sourcelist is going to potentially have items added or removed, it isICollectionrather thanIEnumeration(IEnumerationdoesn’t support modifying the list)
That’s all well and good, except it doesn’t work, the extension method is not found:
Collection<Bitmap> whoHonkers = new Collection<Bitmap>();
whoHonkers.BlowTheirWhoHoovers();

i assume this fails because:
- Visual Studio doesn’t think
CollectionimplementsICollection<T> - Visual Studio doesn’t think
Bitmapdescends fromImage
Now i can change my extension:
public static void BlowTheirWhoHoovers(this Collection<Bitmap> source)
{
...
}
which does compile:

except it’s no longer useful (it requires Collection, and it requires Bitmap), e.g. it fails to work on anything except Collection<T>:
List<Bitmap> whoHonkers = new List<Bitmap>();
whoHonkers.BlowTheirWhoHoovers();
It also fails on anything that it’s Bitmap:
List<Metafile> whoHonkers = new List<Metafile>();
whoHonkers.BlowTheirWhoHoovers();
or
List<PngImage> whoHonkers = new List<PngImage>();
whoHonkers.BlowTheirWhoHoovers();
How can i apply an extension to anything that is:
ICollection<Image>
?
i can’t force anyone to change their declaration, e.g.:
List<Bitmap>
to
Collection<Image>
Update:
Possible avenues of solution exploration:
- finding the syntax that allows extensions on things that the compiler should be able to do
- manually casting the list; doing the compiler’s job for it
Update#2:
i could have simplified some of the distractions around ICollection, and made it IEnumerable (since it’s a hypothetical example i can make up whatever i want). But the screenshots already show Collection, so i’m going to leave it as it is.
Update#3:
As foson pointed out, changing it to IEnumerable allows a way to cheat the answer. So it definitely should stay as ICollection.
Sounds like a covarient problem.
If you change the signature to
public static void BlowTheirWhoHoovers(this IEnumerable<Image> source)you should be able to do it in .NET 4 (not SL).
The problem with varience is that if you passed into the method an
ICollection<JpegImage>, the method itself wouldn’t know that it could only addJpegImages and notBitmaps, defeating type saftey. Therefore the compiler does not let you do it.IEnumerable‘s type parameter is covarient, as seen by theoutkeyword, whileICollection‘s type parameter is not (since it is both in return positions and method parameter positions in the ICollection interface)public interface IEnumerable<out T>http://msdn.microsoft.com/en-us/library/dd799517.aspx