尝试Catch或If语句?

如果你认为有可能获得空指针exception,你应该使用if语句来确保变量不为null,还是应该捕获exception?

我没有看到任何区别,因为您可以将您的逻辑用于处理if语句或catch块中的空指针,那么哪一个是最佳实践?

我会说总是使用逻辑来捕获exception,而不是尝试/ catch。

在validation时应该使用Try / Catch,但是会发生一些奇怪的事情并且会导致错误,因此您可以更优雅地处理它。

这里没有单一的答案, 这取决于它

我们来看几个场景,你可以看到我的意思。

场景:采用不接受null的引用类型参数的方法

您正在定义一个方法,它接受一个引用类型参数,比如说一个流对象,并且您不希望将null作为合法的输入参数接受。

在这种情况下,我会说合同null不是有效的输入。 如果某些代码实际上使用null引用调用该方法,则合同将被破坏。

这是一个例外,更具体地说,它是一个ArgumentNullException 。

例:

 public void Write(Stream stream) { if (stream == null) throw new ArgumentNullException("stream"); ... 

我绝对不会让代码执行,直到它在这种情况下尝试取消引用流,而不是使用NullReferenceException崩溃,因为在那时我失去了所有能力,当我知道原因。

问:为什么我不能返回false而不是抛出exception?

答:因为返回值很容易被忽略,你真的希望你的“写”方法只是默默地跳过写,因为你在调用代码中做了一个snafu,传递了错误的流对象或者无法写入的东西? 我不会!

场景:方法返回对象的引用,有时没有对象

在这种情况下,合同是null是合法的结果。 在我看来, null是值得避免的,因为很难确保你在任何地方都能正确处理,但有时这是最好的方法。

在这种情况下,我会确保if我绕过结果,以确保我在null引用返回时不会崩溃。

概括

如果你仔细看看上面两个场景,你会注意到一件事:

在这两种情况下,它归结为预期的, 合同是什么。

如果合同说“not null ”,则抛出exception。 不要回到旧式API返回false方式,因为不应该忽略exception问题,并且使用if语句乱丢代码以确保每个方法调用成功都不会产生可读代码。

如果合同说“完全可以为null ”,则使用if语句处理它。

广告

为了更好地掌握null问题,我还建议您为您和您的团队获取ReSharper ,但请注意,此答案可应用于任何类型的exception和error handling,同样的原则适用。

有了它可以嵌入到项目中的属性来标记这些情况,然后ReSharper将突出显示有问题的代码。

 public void Write([NotNull] Stream stream) [CanBeNull] public SomeObject GetSomeObject() 

要阅读有关ReSharper使用的合同属性的更多信息,请参阅

  • ReSharper NullReferenceException分析及其契约
  • ReSharper 7中的合同注释

好。 例外就是这样。 例外。 当发生不可预见的事情并且不应该成为正常程序流程的一部分时,它们会被抛出。

这就是这里发生的事情。 您希望在不是时指定参数。 这是意料之外的,因此您应该抛出自己的exception,通知用户。 如果你想获得奖励积分,你还可以包括为什么必须指定参数的原因(如果它不明显)。

我写了一系列关于例外的post: http : //blog.gauffin.org/2013/04/what-is-exceptions/

从表现的角度来看,这实际上取决于你正在做什么。 抛出没有exception时try / catch块对性能的影响很小(如果你真的需要最后几个百分比的性能,你可能应该用C ++重写那部分代码)。 抛出exception会对字符串操作等简单操作产生重大影响; 但是一旦你在循环中获得文件/数据库操作,它们就会慢得多,再次成为一个微不足道的惩罚。 尽管如此,投入App Domain对任何事情都会产生非平凡的影响。

运营绩效/秒:

 Mode/operation Empty String File Database Complex No exception 17,748,206 267,300 2,461 877 239 Catch without exception 15,415,757 261,456 2,476 871 236 Throw 103,456 68,952 2,236 864 236 Rethrow original 53,481 41,889 2,324 852 230 Throw across AppDomain 3,073 2,942 930 574 160 

其他测试结果以及测试源可以从.NET中的exception性能影响中找到

我宁愿建议你使用if-statement来表示NullReferenceexception。 对于其他例外, try-catch应该足够好。

我建议NullReferenceexception的if语句的原因是因为C#不会告诉哪个变量为null。 如果该行有多个对象可能为null,则会丢失跟踪。 如果您使用的是if-statement ,则可以使用更好的日志记录来帮助您获取足够的信息。

主要问题是如果让方法返回Null是个好主意,我个人对此没有任何问题,但是一旦你尝试访问从这个方法返回的对象的修饰符而你忘记检查是否它被分配这成为一个问题。

Ken对此有一个很好的答案 :

如果您总是希望找到一个值,那么抛出exception(如果缺少)。 例外意味着存在问题。

如果值可能丢失或存在且两者都对应用程序逻辑有效,则返回null。

看到这个问题,请看这个问题:

如果您打算表明没有可用数据,则返回null通常是最好的主意。

空对象意味着返回了数据,而返回null则清楚地表明没有返回任何内容。

此外,如果您尝试访问对象中的成员,则返回null将导致nullexception,这对于突出显示错误代码非常有用 – 尝试访问无成员是没有意义的。 访问空对象的成员不会失败意味着错误可能未被发现。

进一步阅读:

  • 没有超出方法范围

  • 我们应该从我们的方法中退出吗?

使用try catch语句不是一个好主意。 因为当你使用try catch它们时,似乎如果出现一些错误,代码将不会打开应用程序。 但是如果你确定会出现什么样的错误,那么你可以点击错误。 这不会产生任何未知错误。 例如。

 string name = null; 

在这里我将使用名称变量,我相信这将抛出Null Refrance错误。

 try { Console.writeLine("Name ={0}",name); } catch (NullRefranceException nex) { //handle the error } catch(Exception ex) { // handle error to prevent application being crashed. } 

这可能是一种很好的做法,同时您可以处理此类错误并使您的代码更具可读性。 喜欢。

 if(name !=null) Console.writeLine("Name ={0}",name); 

根据我的经验,使用if更好,但只有当你真正期望一个空引用指针时。 没有任何代码或上下文,当一个选项优于另一个选项时,很难说。

还有一个优化问题 – try-catch块中的代码不会被优化 。

通常,try-catch块很棒,因为每当发生exception时它们都会中断(移动到catch语句)。 If-else块依赖于您预测错误何时发生。

此外,catch块不会阻止您的代码在发生错误时停止。

它总是更好地使用Try Catch而不是if Here这里的exception是两种类型,即处理UN处理的exception即使你想要处理某些函数,当Exception你可以处理它…

处理exception总是允许您在Catch块Eg中编写一些实现。 警报消息,一种新函数,用于处理何时发生此类exception。