在这行代码中运行:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

这两个问号是什么意思,是某种三元运算符吗?在谷歌里很难查到。


当前回答

它是一个空合并运算符,其工作方式与三元运算符类似。

    a ?? b  => a !=null ? a : b 

另一个有趣的点是,“可为null的类型可以包含值,也可以是未定义的”。因此,如果尝试将可为null的值类型分配给不可为null值类型您将得到一个编译时错误。

int? x = null; // x is nullable value type
int z = 0; // z is non-nullable value type
z = x; // compile error will be there.

所以要使用??操作员:

z = x ?? 1; // with ?? operator there are no issues

其他回答

正如在众多答案中正确指出的那样,“空合并运算符”(??),说到它,您可能还想看看它的表亲“空条件运算符”(.或?[),它是一个多次与??一起使用的运算符??

空条件运算符

用于在执行成员访问(?.)或索引(?[)操作之前测试null。这些运算符可以帮助您编写更少的代码来处理null检查,尤其是在数据结构下降时。

例如:

// if 'customers' or 'Order' property or 'Price' property  is null,
// dollarAmount will be 0 
// otherwise dollarAmount will be equal to 'customers.Order.Price'

int dollarAmount = customers?.Order?.Price ?? 0; 

没有?。和这样做是

int dollarAmount = customers != null 
                   && customers.Order!=null
                   && customers.Order.Price!=null 
                    ? customers.Order.Price : 0; 

这更加冗长和麻烦。

以最简单的方式,两个问号被称为“合并运算符”,它返回链中的第一个非空值。

例如,如果您从一个不可为null的变量中的可为null对象获取值,则可以使用此运算符。即

int a=1;整数?b=空;a=b??0;

上述方程的结果将为零,因为b为空,我们使用了??运算符,这意味着当且仅当b为空时,它将返回0。

int a=1;整数?b=15;a=b??0;

在上式中,a将得到值“15”,因为b具有有效值且不为空。还有,你不能使用??运算符。

在以上示例中,我使用了??0,但是,在??之后也可以使用一个完整的新公式??操作人员

例如a=b??(x==1?10:15)我希望这能澄清你的问题。

两个问号(??)表示它是一个联合运算符。

合并运算符返回链中的第一个非空值。你可以看到这段youtube视频,它实际演示了整个事情。

但让我补充一下视频中的内容。

如果你看到联合的英文意思,它会说“巩固在一起”。例如,下面是一个链接四个字符串的简单合并代码。

因此,如果str1为空,它将尝试str2,如果str2为空,则将尝试str3,依此类推,直到找到具有非空值的字符串。

string final = str1 ?? str2 ?? str3 ?? str4;

简单来说,合并运算符返回链中的第一个非NULL值。

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

相当于

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

但它很酷的一点是,你可以像其他人说的那样,把它们拴起来。没有提到的一点是,您实际上可以使用它来抛出异常。

A = A ?? B ?? throw new Exception("A and B are both NULL");

它是空合并运算符,非常像三元(立即if)运算符。另见??操作员-MSDN。

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

扩展到:

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

其进一步扩展到:

if(formsAuth != null)
    FormsAuth = formsAuth;
else
    FormsAuth = new FormsAuthenticationWrapper();

在英语中,它的意思是“如果左边的东西不是空的,就用那个,否则就用右边的东西。”

请注意,您可以按顺序使用任意数量的这些。以下语句将为Answer分配第一个非空的Answer#(如果所有Answer均为空,则Answer为空):

string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;

另外值得一提的是,虽然上面的展开在概念上是等价的,但每个表达式的结果只计算一次。例如,如果表达式是具有副作用的方法调用,这一点很重要。(感谢@Joey指出了这一点。)