Почему я не могу передать списокк IEnumerable - PullRequest
10 голосов
/ 21 декабря 2011

Этот код генерирует две ошибки времени компиляции:

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

и

Argument 1: cannot convert from 'System.Collections.Generic.List<System.Collections.Generic.List<Foo>>' to 'System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<Foo>>'

Приведение к IEnumberable<List<Foo>> не проблема. Чем отличается приведение внутреннего компонента List от типа, к которому он не работает?

1 Ответ

19 голосов
/ 21 декабря 2011

РЕДАКТИРОВАТЬ: Я только что понял, что я действительно не ответил на аспект, как обойти ограничение. К счастью, это довольно просто:

UseFoos(myFoos.Cast<IEnumerable<Foo>>());

Этот код прекрасно компилируется (когда вы дали имя параметру UseFoos) в C # 4, что вводит универсальную ковариацию и контравариантность для интерфейсов и делегатов.

В качестве более простого примера это работает в C # 4, но не в C # 3:

IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;

Обратите внимание, что даже в C # 4 классы не являются инвариантами, поэтому это не будет работать:

// This won't work
List<string> strings = new List<string>();
List<object> objects = strings;

... и даже для интерфейсов, он поддерживается только тогда, когда это безопасно:

// This won't work either
IList<string> strings = new List<string>();
IList<object> objects = strings;

Интерфейс (или делегат) должен объявить дисперсию самого параметра типа, поэтому если вы посмотрите документацию .NET 4 для IEnumerable<T>, вы увидите, что она объявлена ​​как

public interface IEnumerable<out T>

где out объявляет ковариацию в T.

Эрик Липперт имеет лот подробнее об этом в своем блоге в категории ковариация и контравариантность .

...