在这行代码中运行:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

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


当前回答

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

空条件运算符

用于在执行成员访问(?.)或索引(?[)操作之前测试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; 

这更加冗长和麻烦。

其他回答

注:

我已经阅读了这篇文章和其他许多文章,但我找不到像这样彻底的答案。

由此,我完全理解了“为什么要使用?何时使用?以及如何使用?”

资料来源:

Craig McMurtry发布的Windows通信基础为0-672-32948-4

可为空的值类型

有两种常见的情况,人们想知道值已分配给值类型的实例。第一种是当实例表示数据库中的值时。在这种情况下,希望能够检查实例以确定数据库中是否确实存在值。另一种与本书主题更相关的情况是,当实例表示从某个远程源接收的数据项时。同样,人们希望从实例中确定是否接收到该数据项的值。

.NETFramework2.0包含了一个通用类型定义,它提供了这样的情况,即希望为值类型的实例分配null,并测试该实例的值是否为null。该泛型类型定义是System.Nullable<T>,它将可以替换T的泛型类型参数约束为值类型。从System.Nullable<T>构造的类型的实例可以赋值为null;实际上,它们的值默认为空。因此,从System.Nullable<T>可以称为可为null的值类型。System.Nullable<T>具有一个属性Value,通过该属性值分配给如果实例的值不为空,则可以获得由其构造的类型。因此,可以这样写:

System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}

C#编程语言为声明类型提供了缩写语法由System.Nullable<T>构造。该语法允许缩写:

System.Nullable<int> myNullableInteger;

to

int? myNullableInteger;

编译器将防止试图以以下方式将可空值类型的值分配给普通值类型:

int? myNullableInteger = null;
int myInteger = myNullableInteger;

它阻止人们这样做,因为可为null的值类型可能具有null值,在这种情况下它实际上具有null值并且该值不能分配给普通值类型。尽管编译器将允许该代码,

int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;

第二条语句将导致引发异常,因为如果类型为从System.Nullable<T>构造的函数未分配有效值T,在本例中未发生这种情况。

结论:

将可为null的值类型的值分配给普通值类型的一种适当方法是使用System.nullable<T>.HasValue属性来确定是否已将有效值T分配给可为null值类型:

int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}

另一种选择是使用此语法:

int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;

如果为普通整数myInteger分配了有效整数值,则为其分配可空整数“myNullableInteger”的值;否则,myInteger的值为-1。

这是三元运算符的短手。

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

或者对于那些不做三元的人:

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

这没什么危险。事实上,它很美。如果需要,可以添加默认值,例如:

CODE

int x = x1 ?? x2 ?? x3 ?? x4 ?? 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)我希望这能澄清你的问题。

这里的一些使用合并获取值的示例效率很低。

你真正想要的是:

return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();

or

return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());

这将防止每次重新创建对象。这将确保在创建新对象时分配私有变量,而不是保持私有变量为空并在每次请求时创建新对象。