我有一个构建列表列表的方法。我希望返回类型使用通用的IList<>接口,以减少与下游的具体List<>类型的耦合。然而,编译器在类型转换方面遇到了困难。
public IList<IList<T>> Foo<T>()
{
return new List<List<T>>();
} 当它工作时,为什么它失败:
public IList<T> Foo<T>()
{
return new List<T>();
} 摆脱这种混乱的最优雅的方法是什么?
发布于 2011-11-16 04:03:18
只需执行以下操作:
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>>,那么上面这行代码将无法工作:您将尝试向List<T>的集合中添加一个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)。
发布于 2011-11-16 04:04:26
这与C#协方差和逆方差有关。你可以阅读更多的here。
要执行T接口的接口,您的接口必须同时标记为out T或in T。IEnumerable标记为out T。
https://stackoverflow.com/questions/8142389
复制相似问题