【问题标题】:How can this code throw a NullReferenceException?此代码如何引发 NullReferenceException?
【发布时间】:2010-10-24 16:23:27
【问题描述】:

我一定是疯了,因为我的单元测试失败了,因为下面的代码抛出了一个空引用异常:

int pid = 0;
if (parentCategory != null)
{
    Console.WriteLine(parentCategory.Id);
    pid = parentCategory.Id;
}

抛出它的那一行是:

pid = parentCategory.Id;

console.writeline 只是为了在 NUnit GUI 中调试,但输出的是一个有效的 int。

编辑:它是单线程的,因此不能从其他线程分配给 null,并且 Console.WriteLine 成功打印出该值的事实表明它不应该抛出.

编辑: Category 类的相关 sn-ps:

public class Category
{
    private readonly int id;

    public Category(Category parent, int id)
    {
        Parent = parent;
        parent.PerformIfNotNull(() => parent.subcategories.AddIfNew(this));
        Name = string.Empty;
        this.id = id;
    }
    public int Id
    {
        get { return id; }
    }
}

如果有人想查看完整代码,请访问 Google 代码http://code.google.com/p/chefbook/source/checkout

我想我要尝试重新启动计算机...我已经看到通过重新启动解决了一些非常奇怪的问题。重启后会更新。

更新:谜团解开了。看起来 NUnit 将错误行显示为最后一个成功执行的语句...将测试复制/粘贴到新的控制台应用程序并在 VS 中运行表明它是包含空引用的 if 语句块(未显示)之后的行。感谢大家的所有想法。 +1 给所有回答的人。

【问题讨论】:

  • parentCategory 和 Id 是什么类型?任何隐式运算符?
  • 这有关系吗?检查是否为空,它是单线程的,属性被正确访问,因为 Console.WriteLine 成功。 Id 的类型是 int。
  • 这段代码应该执行得很好,除非你在 Id 属性中做一些连接。不知何故,我觉得你没有告诉我们整个故事。
  • 根据我的经验,这种“不可能”的事情通常是由一些细微的语法错误引起的,比如忘记了大括号、方括号或分号。
  • @Svante 但是编译器应该捕获(大部分)那些东西不是吗?

标签: c# nunit


【解决方案1】:

根据到目前为止的所有信息,我认为要么“抛出的线”是错误的(是什么让你这么想),要么你的“来源”与你构建的程序集不同步。

这看起来不可能,所以一些“理所当然的假设”是错误的,可能是“您正在查看的源代码与您正在调试的过程相匹配”的假设。

【讨论】:

  • @Brian,你不觉得如果他有不匹配的代码 VS 会给他一个警告吗?
  • @Vadim:我可能错过了,但我还没有看到线程上的证据表明他甚至必须使用 VS。
  • 如果代码和程序集不匹配..他如何调试它?
【解决方案2】:

当事情表面上看起来正确时,您很可能会忽略它。您是否 350% 肯定您的 DLL/PDB 与您的源代码匹配,从而为您提供正确的线路?

  • 尝试手动删除您的程序集并运行您正在运行的任何程序。它会失败吗?
  • 尝试清理您的解决方案并重新编译。将程序集复制到任何地方并再次运行。这次有用吗?同一位置的空引用?
  • 调试周围的行以获得您期望的值。 parentCategory 等应符合您的想法。
  • 通过抛出异常修改代码。堆栈跟踪行是否与您的代码中的行完全匹配?

我有过一些非常令人难以置信的经历,因为我的一个假设是错误的。典型的是陈旧的程序集。质疑所有假设。

【讨论】:

  • 我以前肯定见过这种情况。这次不是这样,但肯定要检查一下
【解决方案3】:

不过,没有意义的是 OP 声明 console.writeline 输出一个有效的 int 并且它调用了与他声明抛出错误的行相同的属性。

堆栈跟踪会很有帮助,或者能够查看实际的单元测试。

【讨论】:

    【解决方案4】:

    是的,我们可以看到类别类的代码.. 特别是 Id 属性吗?假设 Id 属性是一个 int(而不是可为空的 int),get 方法必须访问一个 NULL 对象。

    【讨论】:

      【解决方案5】:

      Id 可以是一个可以为空的 int 类型(int?),没有任何值,但是我觉得属性 Id 必须做的不仅仅是返回一个 int,而且里面的东西是 null。

      编辑你的编辑表明这不仅仅是奇怪的,你能给我们提供一个堆栈跟踪吗?

      【讨论】:

        【解决方案6】:

        我不是 C# 方面的专家,我不确定它是否会有所不同,但您是在调试模式还是发布模式下进行调试?如果您处于发布模式,那么您的 IDE 指向的行和问题实际所在的行可能会有所不同(我知道在使用 Visual Studio 时在 C++ 中就是这种情况)

        【讨论】:

          【解决方案7】:

          我不得不同意 Brian... 也许您使用的是过时的 .pdbs,并且您在调试模式下看到的代码与实际调试的代码不符。

          尝试清理项目,并在调试模式下重建它。

          【讨论】:

            【解决方案8】:

            看起来 NUnit 将错误行显示为最后一个成功执行的语句...将测试复制/粘贴到新的控制台应用程序并在 VS 中运行表明它是 if 语句块(未显示)之后的行,其中包含一个 null参考。感谢大家的所有想法。 +1 给所有回答的人。

            【讨论】:

            • 这仍然向我们展示了 Console.WriteLine(parentCategory.Id);正在抛出一个空值。是什么原因造成的?
            • 我将 'line after the if' 解释为 'line after the close-curl of the 'if' 块,例如一些 OP 从未向我们展示过的代码。
            • @lagerdalek - 如果 NUnit 显示最后一个成功的行,并且显示 pid = parentCategory.Id;,然后是 Console.WriteLine(parentCategory.Id);会运行良好。中断的行是 pid =... 之后的行,Davy8 没有向我们展示(没关系)
            • 对,我的意思是 if 块后面没有显示的行。
            猜你喜欢
            • 2018-11-30
            • 2011-11-11
            • 1970-01-01
            • 2014-08-30
            • 2019-04-10
            • 2012-08-06
            • 2020-03-25
            • 2019-02-27
            • 1970-01-01
            相关资源
            最近更新 更多