c# - 返回 IList<IList<T>>

标签 c# generics interface ilist

我有一个构建列表列表的方法。我想让返回类型使用通用 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/

相关文章:

c# - 在 .NET 中播种随机数生成器

c# - 发送命令后更新 UI

c# - 如何在 Windows Phone 中禁用多点触控?

java - 如何在方法中使用类的泛型

c# - 使用通用方法实现接口(interface)

c# - 在 C# 中将字符串转换为日期

java - 如何在 Java 中创建泛型方法?

Java:未经检查的调用 compareTo(T)

.net - 为什么子不能同时实现接口(interface)和处理事件?

c# - MySql 和 SQlite 类实现接口(interface)