Exception handling 这是一个空的try-catch的有效原因,还是有更优雅的解决方案?

Exception handling 这是一个空的try-catch的有效原因,还是有更优雅的解决方案?,exception-handling,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.

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

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.
}
在上面,我不在乎客户是空的还是地址是空的。我的另一个选择是

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

     }
 }

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

对于异常情况,您应该始终使用异常。由于CPU上会出现一些上下文切换,您将遭受性能损失

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

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

 }
例如:

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

上下文切换:

对于异常情况,应始终使用异常。由于CPU上会出现一些上下文切换,您将遭受性能损失

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

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

 }
例如:

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

上下文切换:

如果您知道可能发生这种情况,并且可以避免异常,那么您应该始终检查
null
(或任何情况),原因是异常很慢,并且正如您所指出的,不雅。只需使用:

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

如果您知道可能发生异常,并且可以避免异常,则应始终检查
null
(或任何情况),原因是异常速度慢,并且正如您所指出的,不美观。只需使用:

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

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

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

这是异常的一个非常糟糕的用法。有时会出现“可疑”和“鬼鬼祟祟”的地方,但这完全是错误的。。。糟糕

这是不好的,因为您掩盖了其中所有可能的异常,并且没有向代码中添加关于可能掩盖的内容的自我文档

如果
SavePerson
无法保存此人怎么办(一切都会很愉快地继续下去(好吧,除了没有得救的弗雷德先生……他可能会难过。)

带有显式“null check”的代码没有这个问题,它添加了自我文档。很明显,预期会出现
null
情况(该推理是否有效是另一回事)如果压痕级别的数量是问题,考虑内部方法,不接受“代码> NULL/<代码>值的合同。< /P> 愉快的编码。

这是一个非常糟糕的异常用法。有时会出现“可疑”和“鬼鬼祟祟”的地方,但这完全是……糟糕

这是不好的,因为您掩盖了其中所有可能的异常,并且没有向代码中添加关于可能掩盖的内容的自我文档

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

带有显式“null check”的代码没有这个问题,它添加了自我文档。很明显,预期会出现
null
情况(该推理是否有效是另一回事)如果压痕级别的数量是问题,考虑内部方法,不接受“代码> NULL/<代码>值的合同。< /P>
愉快的编码。

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

  • 与前面提到的其他人一样,使用异常会带来非常高的性能代价(当实际抛出异常时)。对于有效和常见的场景,您通常更希望通过某些条件或方法返回值获得错误指示

  • 即使您确实通过捕获异常来检测可能的情况,建议抛出特定的异常类型,并且只捕获您允许的异常类型。因为如果发生其他错误并引发了不同的异常,该怎么办?(例如,如果通过
    OutOfMemoryException
    保存,您会捕获并忽略它。在您的情况下,即使您尝试捕获并忽略一个异常,也最好只捕获
    NullReferenceException
    ,而忽略其余异常。更好的做法是定义您自己的异常类型(例如,
    CustomerHasNoAddressException
    )并仅捕获该异常


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

  • 与前面提到的其他人一样,使用异常会带来非常高的性能代价(当实际抛出异常时)。对于有效和常见的场景,您通常更希望通过某些条件或方法返回值获得错误指示

  • 即使您确实通过捕获异常来检测可能的情况,建议抛出特定的异常类型,并且只捕获您允许的异常类型。因为如果发生其他错误并引发了不同的异常,该怎么办?(例如,如果通过
    OutOfMemoryException
    保存,您会捕获并忽略它。在您的情况下,即使您尝试捕获并忽略一个异常,也最好只捕获
    NullReferenceException
    ,而忽略其余异常。更好的做法是定义您自己的异常类型(例如,
    customerhasnoaddress)