代码之家  ›  专栏  ›  技术社区  ›  Yes - that Jake.

为什么空引用异常不能命名具有空引用的对象?

  •  12
  • Yes - that Jake.  · 技术社区  · 15 年前

    在我看来,我的很多调试时间都花在了复杂语句中的空引用异常上。例如:

    For Each game As IHomeGame in _GamesToOpen.GetIterator()
    

    为什么,当我得到一个NullReferenceException时,我可以得到堆栈跟踪中的行号,但不能得到等于null的对象的名称。换句话说,为什么:

    Object reference not set to an instance of an object.
    

    _GamesToOpen is not set to an instance of an object.
    

    Anonymous object returned by _GamesToOpen.GetIterator() is null.
    

    game was set to null.
    

    5 回复  |  直到 15 年前
        1
  •  11
  •   Mehrdad Afshari    15 年前

    异常是运行时的东西,变量是编译时的东西。

    表情 null ,运行时将抛出 NullReferenceException . 假设如下:

    Dim a as New MyObject
    Dim b as String = MyObject.GetNullValue().ToString()
    

    如果 GetNullValue() 方法返回 无效的

        2
  •  2
  •   eljenso    15 年前

    对于像Java这样编译成字节码并由VM解释的语言,假设您有一个类 X 有一块田 x ,其价值为 null 供参考。如果你写信

    x.foo()
    

    字节码可能如下所示:

    push Xref           >> top of stack is ref to instance of X with X.x = null
    getField x          >> pops Xref, pushes 'null' on the stack
    invokeMethod foo    >> pops 'null' -> runtime exception
    

        3
  •  1
  •   user68610    15 年前

    捕获此消息的一种简单方法,用于调试在使用前放置断言语句

        4
  •  1
  •   Franci Penov    15 年前

    在发布版本中,变量名从符号中剥离出来,代码甚至可能被优化为没有变量的特定内存位置,而只是将引用保留在其中一个寄存器中(取决于变量的使用范围)。因此,可能无法从引用位置扣除变量的名称。

    在调试构建中,有关于变量的更多信息。但是,异常对象需要以与构建风格无关的方式工作。因此,它在任何口味中都能访问到最低限度的信息。

        5
  •  1
  •   TofuBeer    15 年前

    有几件事。。。

    1) 当你做出自己的特例时,请记住这一点(如果你为此感到烦恼,那么如果你为其他事情而这样做,其他人会对你感到烦恼)。由于异常路径根本不应该是典型的路径,因此花费时间使异常具有有用的信息是非常值得的。

    2) 一般编程实践中,采用这种风格,问题就会少很多(是的,您的代码行会更长,但会节省很多时间):

    a) 永远不要做a.b().c();dox=a.b();x、 c();(在单独的行中)这样您可以看到a的值为null,或者a.b()的返回值为null。

    b) 永远不要将方法调用的返回作为参数传递-始终传递变量。a(foo());应该是x=foo();a(x);这是一个更多的调试和能够看到的价值。

    我不知道为什么像.net和Java这样的环境不提供一个版本的运行时,它确实有关于这些类型异常的更多信息,比如索引在一个超出边界的数组上是什么,变量为null时的名称,等等。。。