Jas*_*rez 6 c# generics ilist interface
我有一个构建列表列表的方法.我想让返回类型使用通用的IList <>接口来减少与下游的具体List <>类型的耦合.但是,编译器正在努力进行类型转换.
public IList<IList<T>> Foo<T>()
{
return new List<List<T>>();
}
Run Code Online (Sandbox Code Playgroud)
为什么这在以下情况下会失败:
public IList<T> Foo<T>()
{
return new List<T>();
}
Run Code Online (Sandbox Code Playgroud)
这个烂摊子最优雅的方式是什么?
Str*_*ior 13
这样做:
return new List<IList<T>>();
Run Code Online (Sandbox Code Playgroud)
因为List<T>implements IList<T>,您将能够添加任何类型IList<T>的结果.例如:
Foo<int>().Add(new List<int>());
Run Code Online (Sandbox Code Playgroud)
至于为什么,这是一个协方差/逆变的问题(我总是让两者混淆).基本上,如果你说你正在返回IList<IList<T>>,那么有人应该能够添加任何类型IList<T>的结果:
Foo<int>().Add(new []{1}); // arrays implement `IList`
Run Code Online (Sandbox Code Playgroud)
显然,如果你返回了一个,List<List<T>>那么上面的代码行将无法工作:你会尝试将a添加T[]到集合中List<T>.所以即使a List<T>是a IList<T>,a List<List<T>>也不是a IList<IList<T>>.
注意:下一部分仅适用于.NET 4及更高版本,因为这是支持接口协方差和逆变的第一个版本.
另一方面,如果您知道消费结果的人不打算在列表中添加任何内容,但只是尝试迭代它,您可以将返回类型更改为IEnumerable<IList<T>>,然后返回就可以了. a List<List<T>>.为什么?因为IEnumerable<T>界面是协变的:
public interface IEnumerable<out T>
Run Code Online (Sandbox Code Playgroud)
"out"告诉编译器这个接口只有返回与T(like GetEnumerator)相关的值的方法,并且它没有任何方法可以将某些相关的东西T作为参数(比如Add).