两个问号在C#中是什么意思?

运行这行代码:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

两个问号是什么意思,是某种三元运算符吗?在Google中查找很难。

605076 次浏览

它是null合并运算符,非常像三元(立即-如果)运算符。另请参阅??运算符-MSDN

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

扩展到:

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

其中进一步扩大到:

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

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

请注意,您可以按顺序使用其中的任意数量。以下语句将把第一个非空Answer#分配给Answer(如果所有答案都为空,则Answer为空):

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

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

??是在值为null时为可空类型提供值的。因此,如果formsAuth为null,它将返回新的FormsAuthean ationWrapper()。

它是null合并运算符。

http://msdn.microsoft.com/en-us/library/ms173224.aspx

是的,几乎不可能搜索,除非你知道它叫什么!:-)

编辑:这是另一个问题的一个很酷的功能。你可以链接它们。

C#的隐藏特性?

它是三元算子的简写。

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

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

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

聚结算子

它相当于

FormsAuth = formsAUth == null ? new FormsAuthenticationWrapper() : formsAuth

只是因为还没有人说过神奇的话:它是零聚结算子。它在C#3.0语言规范的第7.12节中定义。

它非常方便,特别是因为它在表达式中多次使用时的工作方式。形式的表达式:

a ?? b ?? c ?? d

将给出表达式a的结果,如果它是非空的,否则尝试b,否则尝试c,否则尝试d。它在每一点都短路。

此外,如果d的类型不可为空,则整个表达式的类型也不可为空。

谢谢大家,这是我在MSDN网站上找到的最简洁的解释:

// y = x, unless x is null, in which case y = -1.int y = x ?? -1;

只是为了你的娱乐(知道你们都是C#的家伙;-)。

我认为它起源于Smalltalk,在那里它已经存在了很多年。它在那里被定义为:

在对象中:

? anArgument^ self

在未定义对象(又名nil的类)中:

? anArgument^ anArgument

有评估(?)和非评估版本(??)。
它通常在延迟初始化的私有(实例)变量的getter方法中找到,这些变量在真正需要之前保持为nil。

如果你熟悉Ruby,它的||=对我来说似乎类似于C#的??。这是一些Ruby:

irb(main):001:0> str1 = nil=> nilirb(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";

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

代码

int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;

输入图片描述

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

合并运算符从链中返回第一个NON-NULL值。您可以看到这个youtube视频,它实际演示了整个事情。

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

如果您看到合并的英文含义,则表示“合并在一起”。例如,下面是一个简单的合并代码,它链接了四个字符串。

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

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

简单地说,合并运算符从链中返回第一个NON-NULL值。

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

你真正想要的是:

return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();

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

这可以防止每次重新创建对象。而不是私有变量保持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通信基础ISBN 0-672-32948-4

可空值类型

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

. NET Framework 2.0包含一个泛型类型定义,它提供了这样的情况,在这些情况下,人们想要将null分配给值类型的实例,并测试实例的值是否为null。该泛型类型定义为System.Nullable<T>,它将可能替换T的泛型类型参数约束为值类型。从System.Nullable<T>构造的类型实例可以分配一个null值;事实上,它们的值默认为null。因此,从System.Nullable<T>可以称为可为空的值类型。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;

int? myNullableInteger;

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

int? myNullableInteger = null;int myInteger = myNullableInteger;

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

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

第二个语句将导致抛出异常,因为任何尝试访问System.Nullable<T>。值属性是一个无效的操作,如果类型从System.Nullable<T>构造的T没有被赋值,在这种情况下没有发生。

结论:

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

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

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

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

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

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

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

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

int? x = null; // x is nullable value typeint z = 0; // z is non-nullable value typez = 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");

??运算符称为空合并运算符。如果操作数不为空,它返回左侧操作数;否则它返回右侧操作数。

int? variable1 = null;int variable2  = variable1 ?? 100;

如果variable1不为null,则将variable2设置为variable1的值;否则,如果variable1 == null,将variable2设置为100。

其他人已经很好地描述了Null Coalescing Operator。在需要单个null测试的情况下,缩短的语法??=可以增加易读性。

遗留空测试:

if (myvariable == null){myvariable = new MyConstructor();}

使用Null合并运算符可以这样写:

myvariable = myvariable ?? new MyConstructor();

它也可以用缩短的语法编写:

myvariable ??= new MyConstructor();

有些人认为它更具可读性和简洁性。

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

例如,如果您从不可为空的变量中的可空对象获取值,那么您可以使用此运算符。即

int a=1;
int? b=null;
a=b??0;

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

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

在上面的等式中,a将得到值“15”,因为b具有有效期并且不为空。此外,您不能对不可为空的对象使用??运算符。

在上面的例子中,我使用了??0,但是在??运算符之后也可以使用一个完整的新方程。

比如
a=b??(x==1?10:15)
我希望我能回答你的问题