为什么我不能在C#中返回一个类型为List<List<int>>的变量,而函数的返回类型为IList<IList<int>>呢?

4
public IList<IList<int>> FunctionName(...)
{
    var list = new List<List<int>>();
    ...
    //return list;                      // This doesn't compile (error listed below)
    return (IList<IList<int>>)list;     // Explicit cast compiles
}

当我直接返回“list”时,我会收到以下错误:
> "Cannot implicitly convert type
> 'System.Collections.Generic.List<System.Collections.Generic.List<int>>'
> to
> 'System.Collections.Generic.IList<System.Collections.Generic.IList<int>>'.
> An explicit conversion exists (are you missing a cast?)"

接口返回类型不应该接受任何派生实例吗?

1
它对我起作用了 :/。你能给我们提供更多关于框架和语言版本的细节吗? - Misters
3
“接口返回类型不应该接受任何派生实例吗?”- 是的,但是List<List<int>>的接口类型是IList<List<int>>,因为List<T>实现了IList<T>。它并没有说明不同T的类型转换。这由协变和逆变处理。 - poke
@Misters:你使用的是哪个语言版本?我从未见过可以允许那样做的C#编译器。 - recursive
尝试针对 .NET 4.5 和 .NET 4.0 进行目标定位,但出现了相同的错误 :/ - breezeZ
1个回答

6

这里存在一个微妙的类型错误。如果这个问题不解决,你可能会遇到类似的错误。

List<List<int>> list = new List<List<int>>();
IList<IList<int>> ilist = list;  // imagine a world where this was legal

// This is already allowed by the type system
ilist.Add(new int[] { 1, 2, 3 });

// This is actually an array! Not a List<>
List<int> first = list[0];

您可以使用IReadOnlyList<>来满足您的需求。由于它是只读的,所以该类型错误无法在代码中展现。但是您无法向外部列表添加元素或更新值。这种泛型接口的特征被称为“协变性”。
IReadOnlyList<IList<int>> ilist = list;

谢谢。然而,函数签名规定我需要返回IList<IList<int>>,但在函数内部,我确实需要添加项目到列表中以构建它(因此我不能将其设置为只读)。有什么解决办法吗? - breezeZ
@breezeZ:如果你愿意创建一个新的列表,有很多方法可以做到这一点。例如,你可以在最终的ilist上调用.ToList()并获得你想要的结果。 - recursive

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接