C# 中两个问号在一起意味着什么?
-
22-07-2019 - |
题
遇到了这行代码:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
这两个问号是什么意思,是某种三元运算符吗?在谷歌上很难查到。
解决方案
这是空合并运算符,和相当类似的三元(立即如果)运算符。另请参见?操作员 - 。MSDN
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
扩展为:
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
这进一步扩展为:
if(formsAuth != null)
FormsAuth = formsAuth;
else
FormsAuth = new FormsAuthenticationWrapper();
在英语中,它的意思是“如果无论是左侧是不为空,使用,否则使用什么的权利。”
请注意,您可以使用序列中任意数量的这些。下面的语句将分配第一个非空Answer#
到Answer
(如果所有的答案都为空,则Answer
为null):
string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;
另外值得一提的同时上述的膨胀在概念上等同,每个表达式的结果只计算一次。这是重要的,如果例如表达是副作用的方法调用。 (信用到@Joey指出这一点。)
其他提示
只是因为还没有人说过这句神奇的话:这是 空合并运算符. 。它在第 7.12 节中定义 C# 3.0 语言规范.
它非常方便,特别是因为它在表达式中多次使用时的工作方式。形式的表达式:
a ?? b ?? c ?? d
将给出表达式的结果 a
如果它非空,否则尝试 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;
??
是有一种用于空类型提供一个值时的值为空。所以,如果formsAuth为null,则返回新FormsAuthenticationWrapper()。
在两个问号(?)表示,它的一个合并运算符。
合并运算符返回从一个链的第一个非空值。你可以看到这实际上表明了整个事情这YouTube视频。
但让我更添加到视频的话。
如果你看到凝聚的英文含义它说:“巩固起来”。例如下面是一个简单的聚结代码链四个字符串。
因此,如果str1
被null
它会尝试str2
,如果str2
被null
它会尝试str3
等等,直到找到具有非空值的字符串。
string final = str1 ?? str2 ?? str3 ?? str4;
在简单的话合并运算符返回从一个链的第一个非空值。
如果你熟悉红宝石,其||=
似乎类似于C#的??
给我。下面是一些红宝石:
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";
它是三元运算手短。
FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();
或为那些谁不这样做三元:
if (formsAuth != null)
{
FormsAuth = formsAuth;
}
else
{
FormsAuth = new FormsAuthenticationWrapper();
}
没有什么危险这个问题。事实上,它是美丽的。 可以加入预设值,如果这是期望的,例如:
<强> CODE 强>
int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
由于正确地指出在众多的答案是“空合并运算符”(?),其中还可能想看看它的堂兄“空,条件运算符”(讲<强>?或的〔强>),它是许多倍它结合使用与操作者的 ... 强>
用于测试空执行部件存取之前(的?强>)或指数(的〔强>)操作。这些运算符帮助你写更少的代码来处理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;
这是更冗长和麻烦的。
有关只有你的娱乐(知道你是所有的C#家伙; - )。
我认为它起源于Smalltalk中,它已经存在了很多年。它被定义为存在:
在对象:
? anArgument
^ self
在UndefinedObject(又名零的类):
? anArgument
^ anArgument
有两个评估(?)和非评估(??)这个版本。 结果,它在吸气剂的方法往往发现延迟初始化私有(实例)变量,其被留下零直到真正需要。
合并运算符
这相当于
FormsAuth = formsAUth == null ? new FormsAuthenticationWrapper() : formsAuth
一些及彼使用聚结值的实例是低效率的。
你真正想要的是什么:
return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();
或
return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());
此防止对象被重新创建每一次。代替剩余空和一个新的对象在每次请求得到创建的私有变量的,这确保如果创建新对象的专用变量被分配。
注意:的
我已阅读全部此线程和其他许多人,但因为这是我无法找到为完整的答案。
通过其余完全了解的“为什么要使用??以及何时使用??以及如何使用??”
来源:
释放通过克雷格·麦克默特里Windows通信基础 ISBN 0-672-32948-4
空值类型
有其中一个想知道是否两种常见情况 一个值已被分配给一个值类型的一个实例。第一种是当实例表示在数据库中的值。在这种情况下,人们希望能够检查实例,以确定一个值是否确实存在于数据库中。其他情况下,这是更相关的这本书的主题,是当实例表示从一些远程源接收的数据项。再次,一个想从是否接收对于该数据项目的值的实例,以确定
在.NET Framework 2.0采用了通用类型定义,其提供这样的,其中一个要分配空值类型的一个实例,并测试实例的值是否为空的情况。该一般类型的定义是System.Nullable,从而限制了可被取代对于T值类型的一般类型的参数。 从System.Nullable构造类型的实例可以被分配空值;事实上,它们的值默认为空。因此,从类型构造 System.Nullable可以被称为空值类型。 System.Nullable有一个属性,值,通过该值分配给的一个实例 如果实例的值不为空,可以得到从它构造的类型。 因此,可以写为:
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;
它可以防止一个这样做,因为空值类型可以具有值零,这实际上将具有在这种情况下,并且该值不能被分配给一个普通的值类型。虽然编译器将允许此代码,
int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;
在第二语句会导致一个例外,因为任何企图被抛出 访问System.Nullable.Value属性是如果类型的无效操作 从System.Nullable构造尚未分配T的有效值,未在此情况下发生的。
结论:
到一个空值类型的值分配到普通值类型一个适当的方式是使用System.Nullable.HasValue属性,以确定是否T的有效值已被分配给空值类型:
int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}
另一种选择是使用以下语法:
int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;
通过该普通整数myInteger被分配,如果后者已被分配一个有效的整数值可为空的整数“myNullableInteger”的值;否则,myInteger被分配的值为-1。
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
等同于
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
但关于它的很酷的事情是,你可以把它们连,像其他人说。 在一个薄时未触及的是,你实际上可以用它来抛出异常。
A = A ?? B ?? throw new Exception("A and B are both NULL");
在??
运算符称为空合并运算符。如果操作数不为空,则返回左边的操作数;否则返回右手操作数。
int? variable1 = null;
int variable2 = variable1 ?? 100;
设置variable2
到variable1
的值,如果variable1
不为空;
否则,如果variable1 == null
,设置variable2
到100
这是一个空合并运算符的工作方式类似于一个三元运算符。
a ?? b => a !=null ? a : b
此另一个有趣的一点是, “A空类型可以包含值,或者它可以是未定义”。 所以,如果你试图将一个空值类型分配给非可空值类型 你会得到一个编译时错误。
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