可能的空引用异常使用“;作为“;操作人员

本文关键字:作为 操作 引用 异常 | 更新日期: 2023-09-27 18:26:58

在以下代码中:

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#行为/功能。

可能的空引用异常使用“;作为“;操作人员

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

此代码肯定会引发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个具体的不相关的条件你正试图表达。因此,它们都必须进行测试

在这种情况下,您知道发送方实际上是MyObject。因此,使用简单的强制转换而不是as:

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

或者,更好的是:

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

如果强制转换无效,as运算符将返回null。如果事件发送方不属于MyObject,则(发送方为MyObject)==null。

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

由于您可以确定sender==objInstance,因此在验证objInstance之后,只需对objInstance进行操作,而不是强制转换sender!=无效的

这是因为R#并不总是最聪明的。此外,如果senderobjInstance都是null,则仍然可以获得NullReferenceException。无论如何,既然你已经确立了他们的平等,为什么不直接使用objInstance呢?

试试这个:

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

要摆脱歪歪扭扭:

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被传递到其他方法时,情况会变得更糟,这使得我们很难知道代码何时何地会失败。