我似乎陷入了NullReferenceException的巨大麻烦

时间:2010-07-12 03:50:15

标签: c# .net nullreferenceexception

最近,我正在开发一种解析和显示网站XML信息的软件。很简单吧?

我正在获取NullReferenceExceptions的LOADS。例如,这种方法:

private void SetUserFriends(List<Friend> list)
{
    int x = 40;
    int y = 3;

    if (list != null)
    {
        foreach (Friend friend in list)
        {
            FriendControl control = new FriendControl();
            control.ID = friend.ID;
            control.URL = friend.URL;
            control.SetID(friend.ID);
            control.SetName(friend.Name);
            control.SetImage(friend.Photo);

            control.Location = new Point(x, y);
            panel2.Controls.Add(control);

            y = y + control.Height + 4;
        } 
    }
}

我不得不把一个丑陋的包裹作为罪恶如果在实际的foreach循环周围以防止异常。

我觉得我只是把绷带放在轮胎上,而不是实际解决问题。有什么办法可以解决这个问题吗?也许我应该读一本关于编程模式的书,或者不是什么?

真的,我迷路了。我可能会问错误的问题。

6 个答案:

答案 0 :(得分:15)

听起来好像你不确定如果在方法中收到错误参数该怎么办。你现在正在做的事情没有任何内在错误,但更常见的模式是检查方法头部的参数,如果它们不是你所期望的那样就抛出异常:

if (list == null)
{
    throw new ArgumentNullException(list);
}

这是一种常见的防御性编程模式 - 检查以确保您提供的数据通过基本的健全性检查。

现在,如果您自己明确地调用此方法,并且您发现此方法在您不期望它时接收到空list参数,那么是时候查看调用方法的逻辑了。我自己,当我没有元素而不是null时,我宁愿传递一个空列表,以避免出现这种特殊情况。

答案 1 :(得分:4)

我可能会被“无多重出口”人群所淹没,但我通常会在方法开头处通过简单的检查处理:

if (list == null || list.Count == 0) return;

这指定退出条件,然后您不必担心方法中的多个缩进级别。这只有在您能够承受列表为空或空的事实时才有效 - 在某些情况下可能会发生这种情况。

但我同意codeka,因为你需要查看调用代码并确定是否可以从那里改进它。

答案 2 :(得分:2)

似乎你正在寻找防御性编程和参数验证。

正如其他人所说,简单的参数验证对您有用:

if (list == null)
    throw new ArgumentNullException("list");

或者,如果您厌倦了为每个参数不断编写这样的检查,您可以查看许多开源.NET前提条件强制库中的一个。我喜欢CuttingEdge.Conditions

这样,您可以使用以下内容:

Condition.Requires(list, "list").IsNotNull();

但是,设置上述任一前提条件只会指定您的方法不接受空值。 您的问题仍然存在,因为 将空值传递给方法!要解决这个问题,您必须检查调用方法的内容,并确定传入null对象的原因。

答案 3 :(得分:1)

除了抛出ArgumentNullException异常之外,还有一些叫做“Null Obejct Pattern”的东西,如果你希望传递一个null,你可以使用它来指示,例如,某些东西没有'存在,但不希望必须显式检查空值。本质上它是一个实现相同接口的存根类,但它的方法通常是空的或返回足以使它们互补。 http://en.wikipedia.org/wiki/Null_Object_pattern

对于无法表达不存在的值类型也很有用,因为它们不能为空。

答案 4 :(得分:0)

当给出无效输入时,我会提前返回(或提前抛出InvalidArgumentException)。

例如:

private void SetUserFriends(List<Friend> list) 
{ 
    if (list == null) 
        return;

    /* Do stuff */
}

或者,您可以使用常规的空合并模式:

private void SetUserFriends(List<Friend> list) 
{ 
    list = list ?? new List<Friend>();

    /* Do Stuff */
}

答案 5 :(得分:0)

你确实在问错误的问题。正确的问题是“null表示无效输入或表示X的标志”。

在将非空引用类型添加到语言中并使其成为各种API的方式之前,您可以选择在代码中进行显式处理,或者让空引用异常帮助您找到违反期望的位置,然后修复数据/代码这样或那样。