null合并运算符的右关联的行为
本文关键字:关联 运算符 null 合并 | 更新日期: 2023-09-27 17:58:34
空合并运算符是右关联的,这意味着形式的表达式
首先??第二第三个
被评估为
首先??(第二??第三)
根据以上规则,我认为以下翻译是不正确的。
发件人:
Address contact = user.ContactAddress;
if (contact == null)
{
contact = order.ShippingAddress;
if (contact == null)
{
contact = user.BillingAddress;
}
}
收件人:
Address contact = user.ContactAddress ??
order.ShippingAddress ??
user.BillingAddress;
相反,我认为以下是正确的(如果我错了,请纠正我)
Address contact = (user.ContactAddress ?? order.ShippingAddress) ??
user.BillingAddress;
这个规范实际上是自相矛盾的。
C#4规范第7.13节规定:
空合并运算符是右关联的,这意味着操作是从右到左分组的。例如,形式为
a ?? b ?? c
的表达式被评估为a ?? (b ?? c)
。
另一方面,正如已经指出的,7.3.1声称:
除了赋值运算符外,所有二进制运算符都是左关联
我完全同意,对于简单的情况,如何分组并不重要。。。但在的情况下,如果操作数具有不同的类型,则由于隐式类型转换会做一些有趣的事情,因此它可能真的很重要。
我将进一步考虑,ping Mads和Eric,并为C#的相关部分添加一个勘误表(这激发了这个问题)。
编辑:好吧,我现在有一个例子,确实很重要。。。并且空合并运算符肯定是right-关联的,至少在MSC#4编译器中是这样。代码:
using System;
public struct Foo
{
public static implicit operator Bar(Foo input)
{
Console.WriteLine("Foo to Bar");
return new Bar();
}
public static implicit operator Baz(Foo input)
{
Console.WriteLine("Foo to Baz");
return new Baz();
}
}
public struct Bar
{
public static implicit operator Baz(Bar input)
{
Console.WriteLine("Bar to Baz");
return new Baz();
}
}
public struct Baz
{
}
class Test
{
static void Main()
{
Foo? x = new Foo();
Bar? y = new Bar();
Baz? z = new Baz();
Console.WriteLine("Unbracketed:");
Baz? a = x ?? y ?? z;
Console.WriteLine("Grouped to the left:");
Baz? b = (x ?? y) ?? z;
Console.WriteLine("Grouped to the right:");
Baz? c = x ?? (y ?? z);
}
}
输出:
Unbracketed:
Foo to Baz
Grouped to the left:
Foo to Bar
Foo to Bar
Bar to Baz
Grouped to the right:
Foo to Baz
换句话说,
x ?? y ?? z
行为与相同
x ?? (y ?? z)
但与不同
(x ?? y) ?? z
我目前不确定为什么在使用(x ?? y) ?? z
时有两个从Foo到Bar的转换-我需要更仔细地检查。。。
编辑:我现在有另一个问题要讨论双重转换。。。
Jon的回答是正确的。
需要明确的是:C#中的??
运算符是右关联。我刚刚浏览了二进制运算符解析器,并验证了解析器将??
视为正确的关联。
正如Jon所指出的,规范指出??
运算符是右关联的,并且除赋值之外的所有二进制运算符都是左关联的。由于规范本身矛盾,显然只有其中一个是正确的。我会修改规范,说这样的话:
除了简单赋值、复合赋值和零合并运算符外,所有二进制运算符都是左关联
UPDATE:如注释中所述,lambda运算符=>
也是右关联的。
我看不出它有多重要,两者都是:
(a ?? b) ?? c
和
a ?? (b ?? c)
有同样的结果!
两者都按预期工作,并且有效地相同,因为表达式涉及简单的类型(谢谢@Jon Skeet)。在您的示例中,它将从左到右链接到第一个非null。
当将此运算符与不同优先级的运算符组合时,优先级(感谢@Ben Voigt)更有趣:
value = A ?? B ? C : D ?? E;
基本上,关联性本质上是通过运算符优先级或用户引入的子表达式(括号)来表达的。