如果您认为有可能获得空指针异常,您是否应该使用if语句来确保该变量不为null,或者您是否应该捕获异常?
我没有看到任何区别,因为您可以将您的逻辑用于处理if语句或catch块中的空指针,那么哪一个是最佳实践?
答案 0 :(得分:36)
我会说总是使用逻辑来捕获异常,而不是尝试/ catch。
在验证时应该使用Try / Catch,但是会发生一些奇怪的事情并且会出现错误,因此您可以更优雅地处理它。
答案 1 :(得分:18)
这里没有单一的答案,取决于。
我们来看几个场景,这样你就可以看到我的意思了。
场景:采用不接受null
的参考类型参数的方法
您正在定义一个方法,它需要一个引用类型参数,比如说一个流对象,并且您不希望接受null
作为合法的输入参数。
在这种情况下,我会说合同是null
不是有效输入。如果某些代码实际上使用null
引用调用该方法,则合同将被破坏。
这是一个例外,更具体地说,它是ArgumentNullException。
示例:
public void Write(Stream stream)
{
if (stream == null)
throw new ArgumentNullException("stream");
...
我绝对不会让代码执行,直到它在这种情况下尝试取消引用流,而不是使用NullReferenceException崩溃,因为在那时我失去了所有能力,当我知道原因时。
Q值。为什么我不能返回false
而不是抛出异常?
:一种。因为返回值很容易被忽略,你真的希望你的“写”方法只是默默地跳过写,因为你在调用代码中做了一个错误,传递了错误的流对象或者无法写入的东西?我不会!
场景:方法返回对象的引用,有时没有对象
在这种情况下,合同是null
是合法的结果。在我看来,null
是值得避免的,因为很难确保你在任何地方都能正确处理,但有时这是最好的方式。
在这种情况下,我会确保if
绕过结果,确保在null
引用返回时不会崩溃。
<强>概括强>
如果你仔细看看上面两个场景,你会注意到一件事:
在这两种情况下都归结为预期的内容,合同是什么。
如果合同中写着“not null
”,则抛出异常。不要回退到返回false
的旧式API方式,因为不应忽略异常问题,并使用if
语句乱丢代码以确保每个方法调用成功都不会可读代码。
如果合同中说“null
完全有可能”,请使用if
语句处理。
<强>广告强>
为了更好地掌握null
问题,我还建议您为您和您的团队获取ReSharper,但请注意,此答案可应用于任何类型的异常和错误处理,同样的原则适用。
有了属性,您可以嵌入到项目中以标记这些情况,然后ReSharper将突出显示相关代码。
public void Write([NotNull] Stream stream)
[CanBeNull]
public SomeObject GetSomeObject()
要阅读有关ReSharper使用的合同属性的更多信息,请参阅
答案 2 :(得分:4)
好。例外就是这样。例外。当发生不可预见的事情并且不应该成为正常程序流程的一部分时,它们会被抛出。
这就是这里发生的事情。您希望在不是时指定参数。这是意料之外的,因此您应该抛出自己的异常,通知用户。如果您想获得奖励积分,您还可以包括为什么必须指定参数的原因(如果不明显)。
我写了一系列关于例外的帖子:http://blog.gauffin.org/2013/04/what-is-exceptions/
答案 3 :(得分:3)
从表现的角度来看,这实际上取决于你在做什么。抛出没有异常时try / catch块对性能的影响很小(如果你真的需要最后几个百分比的性能,你可能应该用C ++重写那部分代码)。抛出异常会对字符串操作等简单操作产生重大影响;但是一旦你在循环中获得文件/数据库操作,它们就会慢得多,再次成为一个微不足道的惩罚。投掷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
中获取其他测试结果以及测试来源
答案 4 :(得分:0)
我建议您将if-statement
用于NullReference
例外。对于其他例外,try-catch
应该足够好。
我建议NullReference
异常的if语句的原因是因为C#不会告诉哪个变量为null。如果该行有多个对象可能为null,则会丢失跟踪。如果您使用if-statement
,则可以获得更好的日志记录,以帮助您获取足够的信息。
答案 5 :(得分:0)
主要问题是如果让方法完全返回Null是个好主意,我个人对此没有任何问题,但只要您尝试访问从此方法返回的对象的修饰符并且您忘记了检查是否已分配这成为一个问题。
肯有good answer about这个:
如果您总是希望找到一个值,那么抛出异常 如果它丢失了例外意味着存在问题。
如果该值可能丢失或存在且两者都有效 应用程序逻辑然后返回null。
请参阅this disscussion此问题:
如果您打算表明,那么返回null通常是最好的主意 没有数据可用。
空对象意味着已返回数据,而返回null 清楚地表明没有任何回报。
此外,如果您返回null将导致null异常 尝试访问对象中的成员,这可能是有用的 突出显示错误代码 - 试图访问无成员 没有意义。访问空对象的成员不会失败 意思是错误可能未被发现。
进一步阅读:
答案 6 :(得分:0)
使用try catch语句不是一个好主意。因为当你使用try catch它们时,似乎如果出现一些错误,代码将不会打开应用程序。但如果您确定可能出现的错误类型,则可以在此时点击错误。这不会产生任何未知错误。例如。
string name = null;
这里我将使用name变量,我确信这会抛出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);
答案 7 :(得分:0)
根据我使用if
的经验会更好,但前提是您确实期望一个空引用指针。没有任何代码或上下文,当一个选项优于另一个时,很难说。
还有一个优化问题 - try-catch
块won't be optimized中的代码。
答案 8 :(得分:0)
通常,try-catch块很棒,因为每当异常发生时它们都会中断(移动到catch语句)。 If-else块依赖于您预测错误何时发生。
此外,catch块不会阻止代码在发生错误时暂停。
答案 9 :(得分:-2)
除了 if else 之外,使用尝试捕获总是更好 这里的例外有两种类型,即处理和联合国处理例外 即使你想要处理某些功能,当你可以处理它时......
处理异常总是允许您在Catch块中编写一些实现 例如。警报消息,一种新的函数,用于处理何时发生此类异常。