Cannot implicitly convert type 'System.Collections.Generic.List<System.Collections.Generic.List<int>>' to 'System.Collections.Generic.IList<System.Collections.Generic.IList<int>>'

原文地址:c# - Unable to convert List<List<int>> to return type IList<IList<int>> - Stack Overflow

12


For level order traversal why does this exception occur? Following exception occurs:

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?)

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;
}
c#
.net
list
generics
generic-collections
Share
Improve this question
Follow
edited Feb 2, 2018 at 6:35
user avatar
Damien_The_Unbeliever
229k2323 gold badges329329 silver badges428428 bronze badges
asked Feb 2, 2018 at 2:03
user avatar
Tarak
12911 silver badge77 bronze badges
Have you tried return result as IList<IList<int>> ? Or specifying the type of result explicitly, i.e. IList<IList<int>> result = new List<List<int>>();? – 
stuartd
 Feb 2, 2018 at 2:12 
2
A List is an IList and can safely be treated as either. A List<List> and List<IList> cannot because if anything is added to the List which is not a List, it breaks any code treating it as List<List> (it becomes no longer a List<List>). That's the basic issue. Covariance and Contravariance – 
zzxyz
 Feb 2, 2018 at 2:15 
Add a comment
3 Answers
Sorted by:

Highest score (default)

22

Just change the declaration of your result to List<IList<int>>.

List<T> implements IList<T>, but List<List<T>> does not implement IList<IList<int>>. Generic parameters are not covariant or contravariant unless defined that way and IList<T> is not, so the type must match exactly.

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;
}
Share
Improve this answer
Follow
answered Feb 2, 2018 at 2:32
user avatar
Grax32
3,81311 gold badge1616 silver badges3131 bronze badges
Add a comment

0

Pretty sure that if it compiles, doing a cast is a real bad idea. Here's why:

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?
}
As mentioned in my comment, these types of collection issues boil down to covariance and contravariance, and .NET does provide a lot of tools for dealing with them. (Such as various read-only collections and interfaces)

..Which, explains why you get your error as well. There is no implicit cast from List<List> to List<IList> because that cast cannot succeed without breaking type-safety. (and as @Grax mentioned, neither derives from the other)

Share
Improve this answer
Follow
edited Feb 2, 2018 at 2:50
answered Feb 2, 2018 at 2:32
user avatar
zzxyz
2,85411 gold badge1515 silver badges3131 bronze badges
Add a comment

0

There should be explicit conversion and as shown below:-

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

or

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

Share
Improve this answer
Follow
edited Sep 26, 2020 at 3:27
answered Jun 28, 2020 at 5:56
user avatar
Priyanka Thakur
2133 bronze badges
While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply. – 
rizerphe
 Jun 28, 2020 at 6:19

 

posted on 2022-08-18 11:31  ZhYQ_note  阅读(431)  评论(0)    收藏  举报

导航