Try Catch or If statement?
如果您认为有可能获得空指针异常,您应该使用if语句来确保变量不是空的,还是应该只捕获异常?
我看不出有什么不同,因为您可以将处理if语句或catch块中空指针的逻辑放在一起,那么哪个是最佳实践呢?
我会说总是使用逻辑来捕获异常,而不是尝试/捕获。
在验证时应该使用Try/Catch,但是会发生一些奇怪的事情,并且某些事情会导致错误,因此您可以更优雅地处理它。
这里没有一个能满足的答案,这要看情况而定。
让我们来看看我的意思。
方案:采用不接受
您正在定义一个方法,它采用一个引用类型参数,例如流对象,并且您不希望接受
在这种情况下,我会说合同是
这是一个异常,更具体地说,它是一个argumentNullException。
例子:
1 2 3 4 5 | public void Write(Stream stream) { if (stream == null) throw new ArgumentNullException("stream"); ... |
在这种情况下,我绝对不会让代码执行,直到它尝试取消引用流为止,而是使用NullReferenceException崩溃,因为此时,当我知道原因时,我失去了所有的反应能力。
问:为什么我不能返回
A.由于返回值很容易被静默忽略,您真的希望您的"写入"方法只是静默地跳过写入操作,因为您在调用代码中出错,传递了错误的流对象或无法写入的内容?我不会!
场景:方法返回对对象的引用,有时没有对象
在这种情况下,合同是
在这种情况下,我会确保以我的方式绕过结果,以确保我不会在
泛化
如果你仔细观察以上两种情况,你会注意到一件事:
在这两种情况下,归根结底是什么是预期的,什么是合同。
如果合同上说"不是
如果合同上说"
广告
为了更好地掌握
有了它,您可以将属性嵌入到项目中来标记这些情况,然后resharper将突出显示有问题的代码。
1 2 3 4 | public void Write([NotNull] Stream stream) [CanBeNull] public SomeObject GetSomeObject() |
要了解有关Resharper使用的合同属性的更多信息,请参见
- Resharper NullReferenceException分析及其契约
- Resharper 7中的合同注释
好。例外就是这样。例外情况。它们在发生了不可预见的事情时抛出,不应成为正常程序流的一部分。
这就是这里发生的事情。如果参数不是,则应指定该参数。这是出乎意料的,因此您应该抛出自己的异常来通知用户这一点。如果你想得到加分,你也可以包括为什么必须指定参数的原因(如果不明显的话)。
我写了一系列关于例外的文章:http://blog.gauffin.org/2013/04/what-is-exceptions/
从性能的角度来看,这真的取决于你在做什么。在没有抛出异常的情况下,从Test/catch块产生的性能影响是最小的(如果您真的需要最后的百分之几的性能,那么无论如何您都应该在C++中改写代码的那部分)。抛出异常确实会对字符串操作等简单操作产生重大影响;但一旦在循环中得到文件/数据库操作,这些操作就会慢得多,这再次成为微不足道的惩罚。不过,跨应用程序域的抛出对几乎所有事情都会产生不小的影响。
每秒操作性能:
1 2 3 4 5 6 | 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中异常的性能影响文章中获得。
一般来说,Try-Catch块很好,因为每当发生异常时,它们都会中断(移动到catch语句)。如果其他块依赖于您预测错误何时发生。
此外,catch块不会阻止代码在遇到错误时停止。
在我的经验中,使用
还有一个优化问题——
对语句使用try catch不是一个好主意。因为当使用Try-Catch时,如果出现错误,代码似乎不会使应用程序死机。但是,如果你确定会出现什么样的错误,你可以点击那个错误。不会产生任何未知错误。例如.
1 | string name = null; |
这里我将使用name变量,我确信这将引发空折射错误。
1 2 3 4 5 6 7 8 9 10 11 12 | try { Console.writeLine("Name ={0}",name); } catch (NullRefranceException nex) { //handle the error } catch(Exception ex) { // handle error to prevent application being crashed. } |
这不是一个很好的实践,尽管您可以处理此类错误并使代码更可读。喜欢。
1 2 | if(name !=null) Console.writeLine("Name ={0}",name); |
主要的问题是,如果让方法返回空值是一个好主意,我个人对此没有任何问题,但是一旦您尝试访问从该方法返回的对象的修饰符,并且忘记检查它是否被分配,这就成了一个问题。
肯对此有一个很好的答案:
If you are always expecting to find a value then throw the exception
if it is missing. The exception would mean that there was a problem.If the value can be missing or present and both are valid for the
application logic then return a null.
关于这个问题,请看下面的讨论:
Returning null is usually the best idea if you intend to indicate that
no data is available.An empty object implies data has been returned, whereas returning null
clearly indicates that nothing has been returned.Additionally, returning a null will result in a null exception if you
attempt to access members in the object, which can be useful for
highlighting buggy code - attempting to access a member of nothing
makes no sense. Accessing members of an empty object will not fail
meaning bugs can go undiscovered.
进一步阅读:
方法范围之外没有空值
我们应该从方法中返回空值吗?
我建议您使用
我建议使用if语句来处理
使用"尝试捕获"总是比使用"尝试捕获"要好。这里的异常有两种类型,即已处理异常和未处理异常即使你想在你能处理异常的时候处理一些函数…
处理的异常始终允许您在catch块中写入一些实现一条警告信息,当这种异常发生时要处理的新函数。