这是空尝试捕获的正当理由还是有更优雅的解决方案?

时间:2011-06-27 20:23:49

标签: exception-handling

假设我有以下类层次结构:

Person对象包含Customer对象,Customer对象包含Address对象。

我不在乎客户是否有地址,但如果有,我想将其保存到数据库中。所以在这种情况下,有这样的东西是完全没问题的:

try
{
     Address addr = person.Customer.Address;
     db.SaveAddress(addr);
}
catch
{
    //I don't care, but if it is there, just save it.
}

在上面,我不在乎Customer是null还是Address为null。我有另一种选择

 if(person.Customer != null)
 {
     if(person.Customer.Address != null)
     {

     }
 }

如果层次结构很长,则上述情况可能会很长。是否有更优雅的方法来检查对象链是否为空而不必检查每个对象。

5 个答案:

答案 0 :(得分:5)

对于特殊情况,您应始终使用例外。您将受到性能损失,因为CPU上会有一些上下文切换。

您可以将第二个示例与大多数短路语言合并为一行。

 if(person.Customer != null && person.Customer.Address != null)
 {

 }

示例:

 bool isAddressValid = person.Customer != null && person.Customer.Address != null;
 if (isAddressIsValid) { }

上下文切换:http://en.wikipedia.org/wiki/Context_switch

答案 1 :(得分:3)

让您的代码检查条件有几个原因,而不仅仅是捕获任何异常并忽略它。想到的前两个是:

  1. 与其他人提到的一样,使用异常会产生非常高的性能成本(实际抛出异常时)。对于有效且常见的情况,您通常更愿意通过某些条件或方法返回值来指示错误。

  2. 即使您通过捕获异常来检测可能的条件,也建议抛出特定的异常类型,并且只捕获您允许的异常类型。因为如果出现其他问题并且引发了不同的异常怎么办? (例如,如果通过OutOfMemoryException保存怎么办?你会抓住并忽略它)。在你的情况下,即使你去捕捉并忽略异常,最好只捕获NullReferenceException,而忽略其余的。更好的是定义你自己的异常类型(例如CustomerHasNoAddressException)并且只捕获它。

答案 2 :(得分:2)

你应该总是检查null(或任何条件),如果你知道它可能发生,你可以避免异常,原因是异常缓慢,正如你所指出的那样,不优雅。只需使用:

if(person.Customer != null && person.Customer.Address != null) {
    // ...
}

答案 3 :(得分:2)

这是非常糟糕的使用的例外情况。有时会出现“可疑”和“偷偷摸摸”的地方,但这只是彻头彻尾的......

这很糟糕,因为你在其中掩盖每个可能的异常,并在代码中添加 no 自我文档,以及 可能会被掩盖。

如果SavePerson无法拯救这个人怎么办? :(一切都会愉快地继续下去(好吧,除了没有得救的弗雷德先生......他可能会心烦意乱。 )

带有显式“null-check”的代码不会受到此问题的困扰,会添加自我文档。 明显预计null案例(无论该推理是否有效是另一个故事)。如果缩进级别数是问题,请考虑使用合同不接受null的内部方法。

快乐的编码。

答案 4 :(得分:1)

对普通控制流使用异常是一种非常糟糕的做法。由于堆栈展开,try-catch变体可能比空检查慢1000倍。