Try Catch or If statement?

本文关键字:statement If or Catch Try | 更新日期: 2023-09-27 18:20:00

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

我看不出有什么区别,因为你可以把你的逻辑放在if语句或catch块中来处理空指针,那么哪一个是最佳实践?

Try Catch or If statement?

我会说始终使用逻辑来捕获异常,而不是try/catch。

当您进行验证时,应该使用Try/Catch,但发生了一些奇怪的事情,并且某些事情导致了错误,因此您可以更优雅地处理它。

这里没有一个单一的答案就足够了,这取决于

让我们假设几个场景,这样你就能明白我的意思。

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

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

在这种情况下,我认为契约null不是有效的输入。如果某些代码确实使用null引用调用了该方法,则该约定被破坏。

这是一个异常,更具体地说,它是一个ArgumentNullException。

示例:

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

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

Q。为什么我不能返回false而不是抛出异常

A。因为返回值很容易被默默忽略,你真的希望你的"Write"方法因为在调用代码中出错、传递了错误的流对象或无法写入的东西而默默跳过写入吗?我不会的

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

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

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

泛化

如果你仔细观察以上两种情况,你会注意到一件事:

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

如果合同上写着"不是null",则抛出一个异常。不要回到API返回false的旧方式,因为不应该默默地忽略异常问题,并且在代码中丢弃if语句以确保每个方法调用成功不会导致代码可读。

如果合同上写着"null是完全可能的",请使用if语句进行处理。

广告

为了更好地掌握null问题,我也敦促您为您和您的团队获得ReSharper,但请注意,这个答案可以应用于任何类型的异常和错误处理,同样的原则也适用。

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

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

要了解ReSharper使用的合同属性的更多信息,请参阅

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

好吧。只有例外。例外情况。当发生了一些不可预见的事情,并且不应该是正常程序流的一部分时,就会抛出它们。

这就是这里正在发生的事情。您希望指定该参数,但没有指定。这是出乎意料的,因此您应该抛出自己的异常通知用户。如果你想获得加分,你也可以包括为什么必须指定参数的原因(如果不明显)。

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

从性能的角度来看,这实际上取决于您在做什么。当没有抛出异常时,try/catch块对性能的影响是最小的(如果你真的需要最后百分之几的性能,你可能无论如何都应该用C++重写代码的那部分)。抛出异常确实会对更简单的操作(如字符串操作)产生重大影响;但是,一旦在循环中获得文件/数据库操作,它们的速度就会慢得多,因此再次成为一个微不足道的惩罚。不过,在应用程序域中抛出会对任何事情产生不小的影响。

每秒运行性能:

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 中异常的性能含义

我建议您将if-statement用于NullReference异常。对于其他例外,try-catch应该足够好。

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

主要问题是,让方法返回Null是否是个好主意,我个人对此没有任何问题,但一旦你试图访问从该方法返回的对象的修饰符,却忘记检查它是否已分配,这就成了一个问题。

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

如果您总是期望找到一个值,那么抛出异常如果它不见了。例外情况意味着存在问题。

如果该值可能缺失或存在,并且两者对应用程序逻辑然后返回一个null。

请参阅关于这个问题的讨论:

如果您打算表明没有可用的数据。

空对象表示已返回数据,而返回null清楚地表明没有任何东西被归还。

此外,如果您尝试访问对象中的成员,这对于突出显示有缺陷的代码-试图访问nothing的成员毫无意义。访问空对象的成员不会失败这意味着虫子可能会被发现。

进一步阅读:

  • 超出方法范围无空

  • 我们应该从我们的方法中返回Null吗?

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

string name = null;

在这里,我将使用name变量,我确信这将引发Null Refrance Error。

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块非常好,因为每当发生异常时,它们都会中断(移动到catch语句)。如果其他块依赖于您预测错误何时发生。

此外,当遇到错误时,catch块不会阻止代码停止。

使用Try Catch而不是如果其他这里的异常有两种类型,即已处理未处理

处理的异常总是允许您在Catch块内编写一些实现警报消息,当发生这种异常时要处理的新函数。