抛出新的Exception vs Catch块

时间:2009-09-22 22:06:51

标签: c#

之间是否有任何行为差异:

if (s == null) // s is a string
{
 throw new NullReferenceException();
}

try
{
  Console.Writeline(s);
}


catch (NullReferenceException Ex)
{ // logic in here 
}

如果s为null,则抛出null对象的异常。第一个示例更具可读性,因为它准确显示了错误发生的位置(异常位就在导致异常的行旁边)。

我已经通过各种技能水平的各种编码器在各种博客上看到了这种编码风格,但为什么不通过检查s是否为空来执行主逻辑,从而保存异常以免被引发?这种方法有不利之处吗?

由于

5 个答案:

答案 0 :(得分:18)

不,Console.WriteLine(null)不会抛出异常。它只会打印出来。现在假设你的意思是:

Console.WriteLine(s.Length);

然后它才有意义......你应该使用第一种形式。当您无法使用当前信息提前预测时,应该会出现例外情况。如果你能够轻易解决出错的问题,那么尝试一定会失败的操作是没有意义的。它导致代码更难理解并且表现更差。

所以NullReferenceExceptionArgumentNullException之类的内容不应该被捕获,除非它们是由nasty API which sometimes throws exceptions which you can handle, but which shouldn't really be being thrown in the first place引起的。这就是为什么在代码约定中,失败的合同的默认行为是抛出一个你无法明确捕获的异常,而不是通过捕获所有(通常是位于堆栈顶部的某处。)

答案 1 :(得分:2)

正如Jon Skeet已经提到的,Console.WriteLine (null)不会抛出异常。

接下来,我想说你应该'快速失败'。这意味着你必须在你的方法中放入'guard'子句,并检查你的方法中给出的参数,如果它们可以被认为是有效的。 这允许您自己抛出异常,并提供一条在调试时有用的附加消息。该消息可以清楚地指出错误,如果您遇到的NullReferenceException在其消息属性中没有任何好的信息而被抛出则更容易。

答案 2 :(得分:1)

如果您正在编写类库,可能有时您知道如果某个参数包含空值,则可能会导致进一步的麻烦。在这些情况下,我通常发现抛出一个异常是个好主意(尽管我可能会使用ArgumentNullException来解决这个问题)使类库的用户尽可能早地和清楚地意识到这一点。

例外并不总是坏事。

答案 3 :(得分:1)

Jon Skeet是对的,但更一般地说,这都是语义问题。

如果情况具有一定的应用意义(数字超出范围,将来出生日期等),您可能需要在进行任何操作之前测试它并抛出自定义异常(对您的应用有意义的异常) )。

如果情况确实是“例外”,只需编写代码,就像给定值是正确的一样。请参阅,如果您进行测试,您将每次都执行此操作,因为知道VM无论如何都会执行此操作,以防它需要抛出异常。从性能的角度来看,如果错误发生在统计上较小的情况,那就毫无意义了。

答案 4 :(得分:0)

如果您采用Design By Contract类型方法处理事物,那么一段代码可以指定它抛出异常以指定其合同并强制执行。当然,另一半是调用代码来识别合同并履行合同。

在这种情况下,如果你知道一个方法会在传入null时抛出一个异常(即它的合同是你没有传递空值),那么你应该在调用之前进行检查。

Jon Skeet表示该方法无论如何都不会抛出异常。这可能是也可能不是,但保护方法合同的原则(我认为这是你的问题的重点)。