我有一个构建列表列表的方法。我想让返回类型使用通用 IList<> 接口(interface)来减少与下游具体 List<> 类型的耦合。但是,编译器在类型转换方面遇到了困难。
public IList<IList<T>> Foo<T>()
{
return new List<List<T>>();
}
为什么这行得通却失败了:
public IList<T> Foo<T>()
{
return new List<T>();
}
摆脱这种困惑的最优雅的方法是什么?
最佳答案
只需这样做:
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 及更高版本,因为这是第一个支持接口(interface)协变和逆变的版本。
另一方面,如果您知道使用您的结果的人不打算向列表中添加任何内容,而只是试图遍历它,您可以将返回类型更改为 IEnumerable<IList<T>>
然后返回一个 List<List<T>>
就完全没问题了.为什么?因为IEnumerable<T>
接口(interface)是协变的:
public interface IEnumerable<out T>
那个“out”告诉编译器这个接口(interface)将只有返回与T
相关的值的方法。 (如 GetEnumerator
),并且它不会有任何采用与 T
相关的方法作为参数(如 Add
)。
关于c# - 返回 IList<IList<T>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8142389/