如果您认为有可能获得空指针异常,您应该使用 if 语句来确保变量不为空,还是应该只捕获异常?
我看不出有什么区别,因为您可以将逻辑放在 if 语句或 catch 块中处理空指针,那么哪个是最佳实践?
如果您认为有可能获得空指针异常,您应该使用 if 语句来确保变量不为空,还是应该只捕获异常?
我看不出有什么区别,因为您可以将逻辑放在 if 语句或 catch 块中处理空指针,那么哪个是最佳实践?
我想说总是使用逻辑来捕获异常,而不是尝试/捕获。
验证时应该使用 Try/Catch,但是会发生一些奇怪的事情并导致错误,因此您可以更优雅地处理它。
这里没有一个单一的答案就足够了,这取决于。
让我们看几个场景,这样你就可以明白我的意思了。
场景:采用不接受的引用类型参数的方法null
您正在定义一个方法,它需要一个引用类型参数,比如一个流对象,并且您不想接受null
作为合法的输入参数。
在这种情况下,我会说合同不是null
有效的输入。如果某些代码确实使用null
引用调用了该方法,则合同被破坏。
这是一个例外,更具体地说,它是一个ArgumentNullException。
例子:
public void Write(Stream stream)
{
if (stream == null)
throw new ArgumentNullException("stream");
...
在这种情况下,我绝对不会让代码执行,直到它尝试取消引用流,而是以 NullReferenceException 崩溃,因为那时我在知道原因时失去了所有反应能力。
问:为什么我不能返回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 使用的合同属性,请参阅
好。例外就是这样。例外。当发生不可预见的事情并且不应该成为正常程序流程的一部分时,它们会被抛出。
这就是这里发生的事情。您希望在未指定时指定参数。这是出乎意料的,因此您应该抛出自己的异常通知用户。如果您想获得奖励积分,您还可以包括为什么必须指定参数的原因(如果不明显)。
我写了一系列关于异常的帖子: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
应该足够好了。
我建议 if 语句用于NullReference
异常的原因是因为 C# 不会告诉哪个变量为空。如果该行有多个对象可能为空,您将失去跟踪。如果您正在使用if-statement
,则可以使用更好的日志记录来帮助您获得足够的信息。
主要问题是让方法完全返回 Null 是否是个好主意,我个人对此没有任何问题,但是一旦您尝试访问从此方法返回的对象的修饰符并且您忘记检查是否它被分配这成为一个问题。
肯对此有一个很好的回答:
如果您总是期望找到一个值,那么如果它丢失则抛出异常。异常意味着存在问题。
如果该值可能丢失或存在,并且两者都对应用程序逻辑有效,则返回 null。
请参阅有关此问题的讨论:
如果您打算指示没有可用数据,则返回 null 通常是最好的主意。
空对象表示已返回数据,而返回 null 则明确表示未返回任何内容。
此外,如果您尝试访问对象中的成员,返回 null 将导致 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 语句)。If-else 块依赖于您预测错误何时发生。
此外,当遇到错误时,catch 块不会阻止您的代码停止。
使用Try Catch总是比if else更好 这里异常有两种类型,即已处理和未处理的异常即使您想在异常可以处理时处理某些功能...
处理的异常总是允许您在 Catch 块内编写一些实现,例如。警告消息,发生此类异常时要处理的新函数。