Take the 2-minute tour ×

This code generates two compile time errors:

private void DoSomething()
    List<List<Foo>> myFoos = GetFoos();


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


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?

share|improve this question
Are you pre-C# 4.0? stackoverflow.com/questions/1280332/… and stackoverflow.com/questions/730401/upcasting-and-generic-lists may be relevant, if not exact dupes. –  AakashM Dec 21 '11 at 15:52
Are you sure you're using C# 4.0? –  user7116 Dec 21 '11 at 15:53
@AakashM: Correct I'm using 3.5. –  Dan Neely Dec 21 '11 at 16:00
@AakashM Looking at the 3.5 workarounds in those examples; unless/until I actually need to support the inner container being something other than a List<> I think I'll pass. The implementations all fall the uglyness and obviousness checks. –  Dan Neely Dec 21 '11 at 16:23
add comment

1 Answer

up vote 16 down vote accepted

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 UseFoos parameter 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:

IEnumerable<object> objects = strings;

Note that even in C# 4, classes aren't invariant, so this won't work:

// This won't work
List<object> objects = strings;

... and even for interfaces, it's only supported when it's safe:

// This won't work either
IList<object> objects = strings;

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 as

public interface IEnumerable<out T>

where out declares the covariance in T.

Eric Lippert has a lot more about this in his blog category of covariance and contravariance.

share|improve this answer
add comment

Your Answer


