使用“as”运算符可能出现Null Reference Exception

时间:2013-08-09 14:55:24

标签: c# resharper nullreferenceexception

在以下代码中:

MyObject objInstance;

private void someEventHandler(object sender, EventArgs e)
{
    if (sender == objInstance && (sender as MyObject).SomeBoolProperty)
        // Do Something
}

Resharper警告sender as MyObject可能是NullReferenceException。这个代码可以吗?我假设如果sender == objInstance (sender as MyObject)不会返回null,但这不是Resharper消息第一次通知我C#行为/功能我不知道。< / p>

6 个答案:

答案 0 :(得分:6)

当您使用as时,如果无法转换对象(在本例中为null),则会返回MyObject。因此,您的行(sender as MyObject)可能为空。

答案 1 :(得分:5)

此代码肯定会导致NullReferenceException被抛出。考虑objInstancesender具有值null的情况。在这种情况下,sender == objInstance将为true,因为null == null因此sender as MyObject也将返回null,代码将抛出属性访问

编写该代码的最佳方法是

var senderObj = sender as MyObject;
if (senderObj != null && 
    senderObj == objInstance && 
    senderObj.SomeBoolProperty) { 
  // Do something
}

不幸的是,我不相信有一种方法可以显着简化这段代码。您尝试表达的3个特定的无关条件。因此,他们必须全部进行测试

答案 2 :(得分:3)

在这种情况下,您知道发件人确实是MyObject。因此,请使用简单的强制转换而不是as

if (sender == objInstance && ((MyObject)sender).SomeBoolProperty)

或者,甚至更好:

if (sender == objInstance && objInstance.SomeBoolProperty)

答案 3 :(得分:2)

如果您的演员表无效,则as运算符返回null。如果事件发件人不是MyObject,(发件人为MyObject)== null。

如果保证objInstance不为null,那么您的语句将永远不会抛出NullReferenceException。但是,如果objInstance为null,则可能抛出。

由于您可以确定sender == objInstance,因此在验证objInstance!= null之后,只需对objInstance进行操作而不是强制转发发送者。

答案 4 :(得分:1)

这是因为R#并不总是最聪明的。此外,如果NullReferenceExceptionsender都是objInstance,您仍然可以获得null。无论如何,当你建立了他们的平等时,为什么不使用objInstance

请改为尝试:

if (sender == objInstance && objInstance.SomeBoolProperty)

答案 5 :(得分:0)

摆脱波浪形的:

MyObject objInstance;

private void someEventHandler(object sender, EventArgs e)
{
    var myObj = sender as MyObject;

    Debug.Assert(myObj != null);

    if (sender == objInstance && myObj .SomeBoolProperty)
        // Do Something
}

R#理解断言,并会停止警告你。而且,自由插入这些调试断言并不是一种不好的做法。无论何时接收引用类型作为public方法的参数,我都会断言该值不为null,或者在某些情况下抛出异常专门用于接收null参数而不是等待代码失败再向下。当null被传递到其他方法时会变得更糟,这使得很难知道代码将在何时何地失败。