C# IList<;IList<;int>&燃气轮机;不';t接受列表<;列表<;int>>;?

C# IList<;IList<;int>&燃气轮机;不';t接受列表<;列表<;int>>;?,c#,generics,C#,Generics,List实现了IList,所以我希望IList将接受一个List对象 但为什么IList>不接受列表> 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实现了IList,所以我希望IList将接受一个List对象 但为什么IList>不接受列表>

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
    }
静态IList列表_1()
{
列表=新列表{1,2,3,3,4,5};
退货清单;
}
静态IList列表_2()
{
列表父项=新列表();
列表=新列表{1,2,3,3,4,5};
添加(列表);
返回父项;//编译器错误CS0266
}
那么,为什么列表实现了IList

这有点奇怪,因为对象以外的任何类型的列表都不存在 履行ILST的全部合同。这可能是为了让事情变得容易些 更新旧C#1.0代码以使用泛型的人;那些人 我们可能已经确保只有正确的类型进入 他们的名单。大多数情况下,当你通过IList时, 这样被调用方可以通过索引访问列表,而不是 它可以添加任意类型的新项


我建议使用return-IEnumerable而不是IList,这将简化您的生活,因为List完全实现了它。

假设这是可行的。您的客户端代码是:

var result = List_2();
由于合同允许向结果中添加任何
IList
,因此您可能需要

public class MyCustomIList : IList<int>
{
    ...
}
但那是错误的

您的
结果
是一个
列表
的列表,不允许您添加除
列表
或其衍生物以外的任何内容。但是,您可以将
MyCustomIList
添加到
列表中,该列表与无关

如果你需要对这个问题有一个大致的了解,请阅读更多

此特定示例中的基本问题来自
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
}
static IEnumerable List_2()
{
列表父项=新列表();
列表=新列表{1,2,3,3,4,5};
添加(列表);
return parent;//没有错误,可以使用
}

这一直是。

我不知道您为什么要准确返回
IList
,但一种方法是使用:


这两种方法都将运行在所有元素上,并将它们转换为给定的类型,因此我认为最好是返回
IList
(如果可能的话)。

问题在于您的方法
返回类型
。修改方法签名以返回到
IList
,而不是返回
IList

静态IList列表_2()
{
列表父项=新列表();
列表=新列表{1,2,3,3,4,5};
添加(列表);
返回父项;//没有编译器错误
}
现在它可以正常工作了,因为您的方法现在返回一个
列表的
IList
,这是因为

List
实现
IList
但是

List
未实现
IList

这就是为什么第一种方法能按预期工作,而第二种方法不能

只需将第二个方法中的列表声明更改为

List<IList<int>> parent = new List<IList<int>>();
List parent=new List();
这就是协方差和逆变换的情况

泛型类型参数支持协方差和逆变,但您需要以这种方式定义

协方差和逆变换是指能够使用比最初指定的派生类型更多(更具体)或派生类型更少(更具体)的术语。泛型类型参数支持协方差和逆变,以便在分配和使用泛型类型时提供更大的灵活性


您是否理解为什么
列表
不接受
列表
?返回(ILST)父项@那不行,你会得到一个运行时异常。可能是@S的重复ᴇ它不是将一个类型强制转换为一个对象类型,而是IList和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.Cast<IList<int>>().ToList();
}
return parent.ConvertAll(x => (IList<int>)x);
static IList<List<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 compiler error
    }
List<IList<int>> parent = new List<IList<int>>();