在这行代码中运行:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
这两个问号是什么意思,是某种三元运算符吗?在谷歌里很难查到。
在这行代码中运行:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
这两个问号是什么意思,是某种三元运算符吗?在谷歌里很难查到。
当前回答
注:
我已经阅读了这篇文章和其他许多文章,但我找不到像这样彻底的答案。
由此,我完全理解了“为什么要使用?何时使用?以及如何使用?”
资料来源:
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。
其他回答
它是一个空合并运算符,其工作方式与三元运算符类似。
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
它是空合并运算符,非常像三元(立即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指出了这一点。)
注:
我已经阅读了这篇文章和其他许多文章,但我找不到像这样彻底的答案。
由此,我完全理解了“为什么要使用?何时使用?以及如何使用?”
资料来源:
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。
正如在众多答案中正确指出的那样,“空合并运算符”(??),说到它,您可能还想看看它的表亲“空条件运算符”(.或?[),它是一个多次与??一起使用的运算符??
空条件运算符
用于在执行成员访问(?.)或索引(?[)操作之前测试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;
这更加冗长和麻烦。
这是三元运算符的短手。
FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();
或者对于那些不做三元的人:
if (formsAuth != null)
{
FormsAuth = formsAuth;
}
else
{
FormsAuth = new FormsAuthenticationWrapper();
}