无法将List<List<int>>转换为返回类型IList<IList<int>>。

14

为什么进行层序遍历时会出现这个异常?

无法隐式转换类型 'System.Collections.Generic.List<System.Collections.Generic.List<int>>' 到 'System.Collections.Generic.IList<System.Collections.Generic.IList<int>>'。存在显式转换 (是否缺少强制转换?)

public IList<IList<int>> LevelOrder(TreeNode root) 
{
    var result = new List<List<int>>();
    var que = new Queue<TreeNode>();

    //if(root==null) return result;

    que.Enqueue(root);
    while(que.Count!=0)
    {
        int n = que.Count;
        var subList = new List<int>();
        for(int i=0;i<n;i++)
        {
            if(que.Peek().left!=null) 
                que.Enqueue(que.Peek().left);
            if(que.Peek().right!=null)
                que.Enqueue(que.Peek().right);
            subList.Add(que.Dequeue().val);
        }
        result.Add(subList);
    }
    return  result;
}

你尝试过使用 return result as IList<IList<int>> 吗?或者明确指定结果的类型,例如 IList<IList<int>> result = new List<List<int>>(); - stuartd
3
一个 List 是一个 IList,可以安全地被视为任何一个。但是 List<List>List<IList> 不能这样做,因为如果添加到列表中的任何内容不是 List,它就会破坏将其视为 List<List> 的任何代码(它不再是 List<List>)。这是基本问题。协变和逆变。 - zzxyz
3个回答

24
只需将结果的声明更改为List<IList<int>>即可。 List<T> 实现了 IList<T>,但是 List<List<T>> 并不实现 IList<IList<int>>。除非已定义为协变或逆变,否则泛型参数不是协变或逆变的,而 IList<T> 不是,因此类型必须完全匹配。
public IList<IList<int>> LevelOrder(TreeNode root)
{
    var result = new List<IList<int>>();
    var que = new Queue<TreeNode>();

    //if(root==null) return result;

    que.Enqueue(root);
    while (que.Count != 0)
    {
        int n = que.Count;
        var subList = new List<int>();
        for (int i = 0; i < n; i++)
        {
            if (que.Peek().left != null)
                que.Enqueue(que.Peek().left);
            if (que.Peek().right != null)
                que.Enqueue(que.Peek().right);
            subList.Add(que.Dequeue().val);
        }
        result.Add(subList);
    }
    return result;
}

0

我相信如果编译通过,进行强制转换是一个真正的坏主意。原因如下:

public class myStupidList : IList<int>
{
//implementation unimportant
}

private void Button_Click(object sender, RoutedEventArgs e)
{
  var result = new List<List<int>>();
  IList<IList<int>> imNotAListofLists = (IList<IList<int>>)result;
  imNotAListofLists.Add(new myStupidList());
  //result is not a very valid variable right now, is it?
}

如我在评论中所提到的,这些类型的集合问题归结为协变逆变,而.NET提供了许多处理它们的工具。(例如各种只读集合和接口)

这也解释了为什么您会收到错误信息。从List<List>List<IList>没有隐式转换,因为这种转换不能成功而不破坏类型安全性。(正如@Grax所提到的,两者都不是相互派生的)


0

应该进行显式转换,如下所示:

List<IList<int>> result = new List<IList<int>>();

或者

var result = new List<IList<int>>();


虽然这段代码可能解决了问题,但是包括解释它如何以及为什么解决了问题将有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释并指出适用的限制和假设。 - rizerphe

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