Просто сделайте это:
return new List<IList<T>>();
Поскольку List<T>
реализует IList<T>
, вы сможете добавить к результату любой тип IList<T>
. Например:
Foo<int>().Add(new List<int>());
Что касается почему, это вопрос ковариантности/контравариантности (я всегда путаю их). По сути, если вы говорите, что возвращаете IList<IList<T>>
, то кто-то должен иметь возможность добавить любой вид IList<T>
к результату:
Foo<int>().Add(new []{1}); // arrays implement `IList`
Очевидно, что если бы вы вернули List<List<T>>
, то приведенная выше строка кода не сработала бы: вы попытались бы добавить T[]
в коллекцию List<T>
. Таким образом, несмотря на то, что List<T>
является IList<T>
, List<List<T>>
не является IList<IList<T>>
.
Примечание. Следующая часть относится только к .NET 4 и более поздним версиям, поскольку это была первая версия, поддерживающая ковариантность и контравариантность в интерфейсах.
С другой стороны, если вы знаете, что человек, использующий ваш результат, не планирует ничего добавлять в список, а только пытается выполнить итерацию по нему, вы можете изменить тип возвращаемого значения на IEnumerable<IList<T>>
, и тогда было бы совершенно нормально вернуть List<List<T>>
. Почему? Поскольку интерфейс IEnumerable<T>
является ковариантным:
public interface IEnumerable<out T>
Это "out" сообщает компилятору, что этот интерфейс будет иметь только методы, которые возвращают значения, относящиеся к T
(например, GetEnumerator
), и не будет методов, которые принимают что-то, связанное с T
, в качестве параметра ( как Add
).
person
StriplingWarrior
schedule
15.11.2011