List实现了IList,所以我希望IList会接受List对象,但是为什么IList>不接受List>呢?
static IList<int> List_1()
{
List<int> list = new List<int> { 1,2,3,3,4,5};
return list;
}
static IList<IList<int>> List_2()
{
List<List<int>> parent = new List<List<int>>();
List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 };
parent.Add(list);
return parent; //compiler error CS0266
}发布于 2019-05-17 06:15:58
那是因为
List<T>实现了IList<T>但是
List<List<T>>没有实现IList<IList<int>>
这就是为什么您的第一个方法按预期工作,而第二个方法不工作。
只需将第二个方法中的列表声明更改为
List<IList<int>> parent = new List<IList<int>>();这就是协方差和反方差的情况。
泛型类型参数支持协方差和反向方差,但您需要这样定义。
协方差和反方差是指能够使用比最初指定的更派生的类型(更具体的)或更少的派生类型(不那么具体)的能力。泛型类型参数支持协方差和反向方差,以便在分配和使用泛型类型时提供更大的灵活性。
发布于 2019-05-17 05:48:01
假设这是可行的。您的客户代码是:
var result = List_2();由于合同允许在结果中添加任何属于IList<int>的内容,所以您可能有
public class MyCustomIList : IList<int>
{
...
}然后
var result = List_2();
result.Add( new MyCustomIList() );但那是错误的!
您的result是一个List<int>列表,不应该允许您添加除List<int>或其衍生产品之外的任何其他内容。但是,您可以添加MyCustomIList,这是与List<int>无关的。
如果您需要对这个问题有一个全面的了解,请阅读更多关于协方差与反方差的内容。
这个特殊示例中的基本问题来自于Add操作。如果你不需要它,IEnumerable就可以
static IEnumerable<IEnumerable<int>> List_2()
{
List<List<int>> parent = new List<List<int>>();
List<int> list = new List<int> { 1, 2, 3, 3, 4, 5 };
parent.Add(list);
return parent; // no error, this works
}这是已覆盖。
发布于 2019-05-17 05:44:41
那么List为什么要实现IList呢? 这有点奇怪,因为除对象之外的任何类型的List都不能满足IList的全部契约。这可能是为了让更新旧C# 1.0代码的人更容易使用泛型;这些人可能已经确保只有正确的类型才能进入他们的列表。在大多数情况下,当您传递一个IList时,它是为了让被调用者能够通过索引访问列表,而不是这样它可以添加任意类型的新项。
我建议返回IEnumerable而不是IList,这将简化您的生活,因为List完全实现了它。
https://stackoverflow.com/questions/56180152
复制相似问题