当试图将`Concat`与`as`一起使用时,如何理解这个`System.ArgumentNullException`

时间:2015-09-24 03:06:06

标签: c# data-structures casting binary-tree

我正在尝试解决Leetcode问题 Binary Tree Preorder Traversal 。以下是我到目前为止所写的内容:

using System.Collections.Generic;
using System.Linq;

public class TreeNode
{
   public int val;
   public TreeNode left;
   public TreeNode right;
   public TreeNode(int x) { val = x; }
}

public class Solution
{
   public IList<int> PreorderTraversal(TreeNode root)
   {
        if (root == null)
        {
            return new List<int> { };
        }
        else
        {
            IList<int> ret = new List<int> { root.val };
            ret = ret.Concat(PreorderTraversal(root.left)) as IList<int>;
            ret = ret.Concat(PreorderTraversal(root.right)) as IList<int>;// <-- this line
            return ret;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var root = new TreeNode(42);
        root.right = new TreeNode(99);
        var result = new Solution().PreorderTraversal(root);
    }
}

我尝试使用ToList()相同的算法,它有效。但是在运行此代码时,System.ArgumentNullException被抛出到我标记的行。所以我的问题是它来自哪里?怎么理解呢?如何解决?

1 个答案:

答案 0 :(得分:2)

虽然ret的初始值为IList<int>,但使用.Concat时的返回类型为IEnumerable<int>。但是,您使用安全(as)强制转换回IList<Int>;这不是有效的强制转换,因此您的第一个.Concat操作返回null ...然后下一行尝试对空值进行操作。

.Concat是作为扩展方法实现的,它将源(在本例中为ret)作为参数,因此在传递null时抛出ArgumentNullException

您可以使用IEnumerable<int>作为返回类型以及ret的声明并删除您的演员表来解决此问题。

using System.Collections.Generic;
using System.Linq;

public class TreeNode
{
   public int val;
   public TreeNode left;
   public TreeNode right;
   public TreeNode(int x) { val = x; }
}

public class Solution
{
   public IEnumerable<int> PreorderTraversal(TreeNode root)
   {
        if (root == null)
        {
            return Enumerable.Empty<int>();
        }
        else
        {
            IEnumerable<int> ret = new List<int> { root.val };
            ret = ret.Concat(PreorderTraversal(root.left));
            ret = ret.Concat(PreorderTraversal(root.right));
            return ret;
        }
    }
}

 class Program
{
    static void Main(string[] args)
    {
        var root = new TreeNode(42);
        root.right = new TreeNode(99);
        var result = new Solution().PreorderTraversal(root);
    }
}