This code generates two compile time errors:
private void DoSomething()
{
List<List<Foo>> myFoos = GetFoos();
UseFoos(myFoos);
}
private void UseFoos(IEnumerable<IEnumerable<Foo>>)
{
}
The best overloaded method match for 'NameSpace.Class.UseFoos(System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<Foo>>)' has some invalid arguments
and
Argument 1: cannot convert from 'System.Collections.Generic.List<System.Collections.Generic.List<Foo>>' to 'System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<Foo>>'
Casting to IEnumberable<List<Foo>> isn’t a problem. What’s different about casting the inner List component of the type that it fails?
EDIT: I’ve just realized that I haven’t really answered the aspect of how to work around the limitation. Fortunately it’s quite easy:
That code compiles fine (when you’ve given the
UseFoosparameter a name) under C# 4, which introduced generic covariance and contravariance for interfaces and delegates.As a simpler example, this works in C# 4 but not in C# 3:
Note that even in C# 4, classes aren’t invariant, so this won’t work:
… and even for interfaces, it’s only supported when it’s safe:
The interface (or delegate) has to declare the variance of the type parameter itself, so if you look at the .NET 4 documentation for
IEnumerable<T>you’ll see it’s declared aswhere
outdeclares the covariance inT.Eric Lippert has a lot more about this in his blog category of covariance and contravariance.