C#中两个问号共同意味着什么?

时间:2009-01-15 14:03:13

标签: c# null-coalescing-operator

跨越这一行代码:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

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

19 个答案:

答案 0 :(得分:1948)

它是空合并运算符,非常类似于三元(立即数)运算符。另请参阅?? Operator - MSDN

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

扩展为:

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

进一步扩展到:

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

在英语中,它表示“如果左边的任何内容不为空,请使用它,否则使用右边的内容。”

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

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

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

答案 1 :(得分:263)

因为没有其他人说过神奇的话:它是 null合并运算符。它在C# 3.0 language specification的第7.12节中定义。

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

a ?? b ?? c ?? d
如果表达式a非空,

将给出结果{否},否则请尝试b,否则请尝试c,否则请尝试d。它在每个点都短路。

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

答案 2 :(得分:67)

这是空合并运算符。

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

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

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

Hidden Features of C#?

答案 3 :(得分:25)

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

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

答案 4 :(得分:20)

当值为null时,

??可以为可空类型提供值。因此,如果formsAuth为null,它将返回新的FormsAuthenticationWrapper()。

答案 5 :(得分:18)

enter image description here

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

Coalescing运算符返回链中的第一个NON-NULL值。你可以看到this youtube video,它实际上展示了整个事物。

但是,让我在视频中添加更多内容。

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

因此,如果str1null,它会尝试str2,如果str2null则会尝试str3,依此类推找到一个非空值的字符串。

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

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

答案 6 :(得分:12)

如果你熟悉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";

答案 7 :(得分:11)

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

<强> CODE

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

答案 8 :(得分:11)

这是三元运营商的简称。

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

对于那些不做三元的人:

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

答案 9 :(得分:10)

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

我认为它起源于Smalltalk,它已存在多年。它定义为:

对象中的

? anArgument
    ^ self

在UndefinedObject(又名nil的类)中:

? anArgument
    ^ anArgument

有评估(?)和非评估版本(??)。 通常在getter-methods中找到惰性初始化的私有(实例)变量,这些变量在真正需要之前保持为零。

答案 10 :(得分:10)

合并运算符

它相当于

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

答案 11 :(得分:10)

正如许多答案中正确指出的那样是“空合并运算符”( ?? ),说到你可能还想看看它的堂兄“Null-conditional Operator”(<强>?或?[)这是一个多次与 ??

一起使用的运算符

Null-conditional Operator

  

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

更冗长,更麻烦。

答案 12 :(得分:9)

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

你真正想要的是:

return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();

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

这可以防止每次都重新创建对象。而不是私有变量保持为null并且在每个请求上创建一个新对象,这确保在创建新对象时分配私有变量。

答案 13 :(得分:7)

注意:

我已经阅读了整个这个主题和其他许多内容,但我找不到这样的答案。

我完全理解&#34;为什么要使用?什么时候用?以及如何使用??。&#34;

来源:

Windows通信基础由Craig McMurtry释放 国际标准书号0-672-32948-4

Nullable Value Types

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

.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的值类型可以具有null值,在这种情况下它实际上具有该值,并且该值不能分配给普通值类型。虽然编译器允许使用此代码,但

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分配可空整数的值&#34; myNullableInteger&#34;如果后者已被赋予有效的整数值;否则,myInteger的值为-1。

答案 14 :(得分:2)

其他人对Null Coalescing Operator的描述很好。如果需要对null进行一次测试,则缩短的语法??=可以增加可读性。

旧版null测试:

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

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

myvariable = myvariable ?? new MyConstructor();

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

myvariable ??= new MyConstructor();

有些人觉得它更具可读性和简洁性。

答案 15 :(得分:1)

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

相当于

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

但关于它的一个很酷的事情就是你可以像其他人说的那样把它们联系起来。 没有涉及的一个问题是你实际上可以使用它来抛出异常。

A = A ?? B ?? throw new Exception("A and B are both NULL");

答案 16 :(得分:0)

它是一个空合并运算符,与三元运算符的工作方式类似。

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

另一个有趣的观点是, &#34;可空类型可以包含值,也可以是未定义的&#34; 。 因此,如果您尝试将可空值类型分配给不可为空的值类型 您将收到编译时错误。

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

答案 17 :(得分:0)

??运算符称为null-coalescing运算符。如果操作数不为null,则返回左侧的操作数;否则,返回0。否则返回右手操作数。

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

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

答案 18 :(得分:-1)

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

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

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

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

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

在上面的等式中,a 将获得值“15”,因为 b 具有有效值并且不为空。 还有,你不能用??不可为空对象上的运算符。

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

比如
a = b ?? ( x==1 ? 10 : 15)
我希望它可以解决您的问题。