遍历以下代码行:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
这两个问号是什么意思,是某种三元运算符吗?在Google中很难查找。
遍历以下代码行:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
这两个问号是什么意思,是某种三元运算符吗?在Google中很难查找。
Answers:
它是空值合并运算符,与三元运算符(即时if)非常相似。另请参阅?? 运营商-MSDN。
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
扩展为:
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
进一步扩展为:
if(formsAuth != null)
FormsAuth = formsAuth;
else
FormsAuth = new FormsAuthenticationWrapper();
在英语中,它的意思是“如果左边的内容不为空,则使用它,否则使用右边的内容。”
请注意,您可以依次使用任何数量的这些。以下语句将第一个非null分配Answer#
给Answer
(如果所有Answers为null,则the Answer
为null):
string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;
同样值得一提的是,以上扩展在概念上是等效的,每个表达式的结果仅计算一次。例如,如果表达式是具有副作用的方法调用,则这一点很重要。(请指出@Joey,以指出这一点。)
??
保持关联,所以a ?? b ?? c ?? d
等效于((a ?? b) ?? c ) ?? d
。“赋值运算符和三元运算符(?:)都是右关联的。所有其他二进制运算符都是左关联的。” 来源:msdn.microsoft.com/en-us/library/ms173145.aspx
只是因为没有人说过神奇的话:它是null合并运算符。它在C#3.0语言规范的 7.12节中定义。
它非常方便,特别是因为它在表达式中多次使用时的工作方式。形式的表达式:
a ?? b ?? c ?? d
a
如果为非null,则将给出表达式的结果,否则尝试b
,否则尝试c
,否则尝试d
。它在每个点都短路。
同样,如果的类型d
是不可为空的,则整个表达式的类型也将不可为空。
它是空合并运算符。
http://msdn.microsoft.com/en-us/library/ms173224.aspx
是的,除非您知道它的名字,否则几乎不可能进行搜索!:-)
编辑:这是另一个问题的一个很酷的功能。您可以将它们链接起来。
谢谢大家,这是我在MSDN站点上找到的最简洁的解释:
// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
-1
只是一个普通的int
,不可为null)。
x
是类型int?
,但是y
是类型int
,则可以编写int y = (int)(x ?? -1)
。如果不是,它将解析x
为,或者将其分配为如果是。int
null
-1
y
x
null
两个问号(??)表示其为合并运算符。
合并运算符从链返回第一个NON-NULL值。您可以观看此youtube视频,它实际上演示了整个过程。
但是,让我在视频中添加更多内容。
如果您看到合并的英文含义,那就说“巩固在一起”。例如,下面是一个简单的合并代码,它链接了四个字符串。
所以,如果str1
是null
,它会尝试str2
,如果str2
是null
,它会尝试str3
依此类推,直到它找到一个非空值的字符串。
string final = str1 ?? str2 ?? str3 ?? str4;
用简单的话说,合并运算符从链中返回第一个NON-NULL值。
这是三元运算符的简写。
FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();
或对于那些不做三元的人:
if (formsAuth != null)
{
FormsAuth = formsAuth;
}
else
{
FormsAuth = new FormsAuthenticationWrapper();
}
!= null
)和第二个formsAuth
(在之后?
);在空合并形式中,两个都隐式采用您提供的值。
如果您熟悉Ruby,那么对我来说,它就像||=
C#??
。这是一些Ruby:
irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"
在C#中:
string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";
x ||= y
对像x = x || y
这样的东西,??
实际上更类似于||
Ruby中的plain 。
??
只关心null
,而||
在Ruby中操作,因为在大多数语言中,更多的是null
,false
或者任何可以被认为是具有价值的布尔false
(在某些语言如""
)。这不是一件好事或坏事,只是一个区别。
没什么危险的。实际上,它是美丽的。如果需要,可以添加默认值,例如:
码
int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
int? x1 = null;
是吗
x1
- x4
必须是可空类型:它是没有意义的说法,有效“的结果是0
,如果x4
是,它不可能采取值”( 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;
这比较冗长和繁琐。
这里使用合并获得价值的一些示例效率很低。
您真正想要的是:
return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();
要么
return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());
这样可以防止每次都重新创建对象。这样,可以确保在创建新对象时分配私有变量,而不是使私有变量保持为空并在每次请求时都创建一个新对象。
??
评估捷径吗?仅当为nil时new FormsAuthenticationWrapper();
评估。 _formsAuthWrapper
我已经阅读了整个主题以及其他主题,但是找不到如此详尽的答案。
通过它,我完全理解了“为什么使用??,何时使用??以及如何使用”。
Windows通信基础已释放Craig McMurtry ISBN 0-672-32948-4
在两种常见情况下,您想知道是否已将值分配给值类型的实例。第一种是实例代表数据库中的值时。在这种情况下,我们希望能够检查实例以确定数据库中是否确实存在值。另一种情况是与实例有关的,当实例表示从某个远程源接收到的数据项时。同样,人们想根据实例确定是否接收到该数据项的值。
.NET Framework 2.0包含一个通用类型定义,该定义提供了类似的情况,在这种情况下,您希望为值类型的实例分配null,并测试该实例的值是否为null。该通用类型定义为System.Nullable,它将可替换T的通用类型参数约束为值类型。从System.Nullable构造的类型的实例可以分配为null值;实际上,它们的值默认为空。因此,从System.Nullable构造的类型可以称为可为空的值类型。System.Nullable具有属性Value,如果该实例的值不为null,则可以通过该属性获得分配给从其构造的类型的实例的值。因此,可以写出:
System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}
C#编程语言提供了一种简短的语法,用于声明从System.Nullable构建的类型。该语法允许缩写:
System.Nullable<int> myNullableInteger;
至
int? myNullableInteger;
编译器将以这种方式防止尝试将可为空的值类型的值分配给普通值类型:
int? myNullableInteger = null;
int myInteger = myNullableInteger;
它阻止了这样做,因为可为空的值类型可能具有null值(在这种情况下它实际上会具有此值),并且该值不能分配给普通的值类型。尽管编译器允许使用此代码,
int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;
第二条语句将引发异常,因为如果从System.Nullable构造的类型尚未分配有效的T值,则任何尝试访问System.Nullable.Value属性的操作都是无效操作,而在此操作中没有发生案件。
将可空值类型的值分配给普通值类型的一种正确方法是使用System.Nullable.HasValue属性来确定是否已将T的有效值分配给可空值类型:
int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}
另一种选择是使用以下语法:
int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;
如果为空整数“ myNullableInteger”分配了有效的整数值,则通过该值将普通整数myInteger分配给它;否则,将为myInteger分配值-1。
这是一个空合并运算符,其作用与三元运算符相似。
a ?? b => a !=null ? a : b
另一个有趣的地方是, “可为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
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
相当于
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
但是,最酷的是您可以像其他人一样将它们链接起来。尚未触及的一个问题是您可以实际使用它引发异常。
A = A ?? B ?? throw new Exception("A and B are both NULL");
其他人描述Null Coalescing Operator
得很好。对于那些感兴趣的人,这里有一个简化的语法(SO问题):
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
等效于此:
FormsAuth ??= new FormsAuthenticationWrapper();
有些人认为它更易读和简洁。