C#6.0 / New null检查语法的新语法有何不同?

时间:2016-04-27 09:44:30

标签: c# visual-studio c#-6.0

首先,我为这个问题中使用的标题道歉,因为我甚至不知道如何询问它,也不知道如何搜索它,所以它可能存在于某个地方,类似于此问题之一。

我最近在Visual Studio 2015上遇到了一个我以前从未见过的潜在修复。在构建EventHandlers时,我通常会这样做:

public event EventHandler MyEvent;

internal void onMyEvent(EventArgs eventArgs) {
    if(MyEvent != null) {
        MyEvent(this, eventArgs);
    }
}

但是现在,Visual Studio 2015会使if语句和相应的括号变灰,并且在悬停时会显示一条消息,指出可以简化委托调用。简化版本看起来像这样:

public event EventHandler MyEvent;

internal void onMyEvent(EventArgs eventArgs) {
    MyEvent?.Invoke(this, eventArgs);
}

这是如何运作的?如果在“”之前的表达式中调用Exception中的方法或代码停止执行,则不会抛出null是空的吗?

另外,我是否可以使用“”替换检查变量/方法/方法是否为if的每个null语句,而不考虑代码的可读性?

旁注: 我假设这是来自新版本的C#,6.0,因为我以前从未见过它。如果我错了,请纠正我

2 个答案:

答案 0 :(得分:12)

正如它所指出的那样,这个C#6特征被称为Null-conditional Operators

还值得研究使用ILSpy生成的C#代码:

internal void onMyEvent(EventArgs eventArgs)
{
    EventHandler expr_07 = this.MyEvent;
    if (expr_07 != null)
    {
        expr_07(this, eventArgs);
    }
}

如您所见,这是一个纯粹的编译器功能..它只是将您的代码重写为传统的空检查。

回答你的问题(虽然我猜你已经通过查看代码来解决这个问题):

  

由于调用了一个方法,不会抛出异常   null或代码停止执行,如果表达式在'?'之前是空的吗?

当你的eventhandler为null时,不会抛出异常。当一个对象在?之前执行时,代码才会被执行?是空的。

现在直到这一点,这只是一个方法调用。显然,如果你想要一个带有Null条件运算符的表达式结果的值,它有点复杂:如果它是一个引用类型,那么你的变量保持为null,但如果它是一个值类型那么它将自动为空,如果您使用'?'的对象,它也将为null。 operator为null。

以下是针对此案例的解编译代码:

Program.Customer[] array = new Program.Customer[10];
    if (array == null)
    {
        int? arg_33_0 = null;
    }
    else
    {
        Program.Customer expr_1A = array[0];
        if (expr_1A == null)
        {
            int? arg_33_0 = null;
        }
        else
        {
            new int?(expr_1A.IntField);
        }
    }

答案 1 :(得分:2)

简化......

MyEvent?.Invoke(this, eventArgs);中的,称为Null Conditional Operator,用于简化代码。

在调用方法或访问可枚举的索引(例如ArrayList之前),它们用于测试null。

这个例子可以在关于Null Condition Operator的页面上找到,它是自我解释的:

// null if customers is null
int? length = customers?.Length;

// null if customers is null
Customer first = customers?[0];

// null if customers, the first customer, or Orders is null
int? count = customers?[0]?.Orders?.Count();