我正在查看一些代码(Delphi 7),每个特定对象的方法调用顶部都有以下检查:
if not Assigned(self) then
raise Exception.CreateRes(@sAbstractError);
{ Real code for this method}
我猜这样做可以避免我尝试在空对象指针上调用方法。但是如果我尝试在这种情况下访问成员数据,我会立即得到异常,对吗?
这是一种我从未见过的标准吗?所涉及的对象派生自TPersistent。
一个清晰的错误提示关于空指针的问题比一个没有解释原因的访问违规更好。
尽管这不是你想有意做的事情,但你可以在空指针上调用实例方法。当发生这种情况时,执行会一直继续,直到需要访问实例数据,然后就会出错。
在这种情况下,检查是否为nil会在过程的顶部警告你,这样你就可以做一些不同的事情,比如记录堆栈跟踪。或者你可以在引发错误的代码行上设置断点,以便深入了解发生了什么。
也就是说,如果我正在尝试追踪一个使用了nil引用的特定Bug,我可能会这样做。
但是如果经常这样做,我认为这可能是一种代码异味。
这是一个绝对会导致崩溃的情况(例如操作系统异常,如“从地址0x00000000读取”)。抛出语言异常只是多余的(在此误用EAbstractError并不能使其更好)。
在不安全的语言中检查有效输入参数是不可行的,因为您永远无法获得确定性,因此您对无效参数的处理将永远不一致。(为什么当传递nil指针时会引发异常,但是当传递0x00000001时不会引发异常,而这也是无效的?)有关此问题的更多技术讨论,请阅读Larry Osterman有关不要检查有效指针的原因博客。
应该注意一个例外情况:在Delphi中,可以对空指针调用 Free
方法,这当然需要进行那种检查。
然后总有可能当使用 nil Self 运行时代码不会崩溃。例如 - 如果它没有访问所有者对象的任何字段。在这种情况下,这个测试将捕获本来无法检测到的问题。
尽管如此,这是极端防御性编程。我从不这样做(好吧,几乎从不 - 只有在我追逐兔子...呃...解决 bug 时)。
看起来该方法的原意是成为一个抽象方法。