返回 IList>
我有一个构建列表列表的方法。我想让返回类型使用通用 IList<>接口以减少与具体 List<> 的耦合类型下游。然而,编译器在类型转换方面遇到了困难。
public IList<IList<T>> Foo<T>()
{
return new List<List<T>>();
}
当它有效时为什么会失败:
public IList<T> Foo<T>()
{
return new List<T>();
}
摆脱这种混乱的最优雅的方法是什么?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
只需这样做:
因为
List
实现了IList
,因此您将能够添加任何类型的IList
到结果。例如:至于为什么,这是协方差/逆变的问题(我总是把两者混淆)。基本上,如果您说您要返回一个
IList>
,那么有人应该能够添加任何类型的IList 。
结果:显然,如果您返回了
List
那么上面的代码行将不起作用:您将尝试添加一个>
T[]
到List
的集合。因此,即使List
是IList
,List
也不是>
>IList>
。注意:下一部分仅适用于 .NET 4 及更高版本,因为这是第一个支持接口协变和逆变的版本。
另一方面,如果您知道使用您的结果的人是不打算向列表中添加任何内容,而只是尝试迭代它,您可以将返回类型更改为
IEnumerable>
然后就可以了返回一个List
。为什么?因为>
IEnumerable
接口是协变的:“out”告诉编译器该接口将只具有返回相关值的方法
T
(如GetEnumerator
),并且它不会有任何将与T
相关的内容作为参数的方法(如Add )。
Just do this:
Because
List<T>
implementsIList<T>
, you will be able to add any kind ofIList<T>
to the result. For example:As to the why, this is a matter of covariance/contravariance (I always get the two mixed up). Basically, if you say you're returning an
IList<IList<T>>
, then someone should be able to add any kind ofIList<T>
to the result:Obviously if you had returned a
List<List<T>>
then the above line of code wouldn't work: you would be attempting to add aT[]
to the collection ofList<T>
. So even though aList<T>
is anIList<T>
, aList<List<T>>
is not anIList<IList<T>>
.Note: This next portion only applies to .NET 4 and up, as that was the first version to support covariance and contravariance in interfaces.
On the other hand, if you know that the person consuming your result isn't planning to add anything to the list, but is only trying to iterate across it, you could change your return type to
IEnumerable<IList<T>>
and then it would be perfectly fine to return aList<List<T>>
. Why? Because theIEnumerable<T>
interface is covariant:That "out" tells the compiler that this interface will only have methods that return values related to
T
(likeGetEnumerator
), and it won't have any methods that take something related toT
as a parameter (likeAdd
).这与 C# 的协变和逆变有关。您可以在此处阅读更多内容。
要执行 T 的接口的接口,您的接口必须都标记为 out T 或 in T。IEnumerable 标记为 out T。
That is related to C# covariance and contravariance. You can read more here.
To do interface of interface of T, your interfaces must both be marked as either out T or in T. IEnumerable is marked as out T.