空合并运算符的工作原理

How null-coalsescing operator works

我得到了三个继承自接口 'IFoo' 的 类(classA、classB 和 classC);如果使用这个

var fooItem = (request.classAitem ?? (request.classBitem  as IFoo ?? request.classCitem)) 

var fooItem = (request.classAitem ?? request.classBitem ?? request.classCitem as IFoo)

它工作得很好,但其他组合甚至无法编译:

var fooItem = (request.classAitem as IFoo ?? request.classBitem ?? request.classCitem)

var fooItem = (request.classAitem ?? request.classBitem ?? request.classCitem) as IFoo

在我看来,在某些情况下,编译器会隐式地将子 类 取消装箱到它们的 IFoo 接口,但在其他一些情况下则不会。大家怎么看?

在你的两个例子中都不起作用,因为 ?? 是右结合的,我们首先尝试确定这个表达式的数据类型:

request.classBitem ?? request.classCitem

如果数据类型不同,数据类型只能是其输入之一的数据类型。显然这里的任何一个方向都没有可用的转换,所以你会得到一个编译器错误。请注意,编译器 不会 决定这里的数据类型是 IFoo 只是因为 类 碰巧实现了它(如果实现了,如果会发生什么他们都实现了多个通用接口?)

将此与您的前两个示例进行比较。首先,我们首先考虑这个表达式:

request.classBitem  as IFoo ?? request.classCitem

此表达式的类型是 IFoorequest.classCitem 的任何数据类型。存在从 request.classCitem 类型到 IFoo 类型的转换,因此显然选择了它,因此整个表达式的数据类型为 IFoo。然后用于确定整个表达式的类型(同样,IFoo)。

第二种情况很相似,因为??是右结合1,我们首先要判断的类型是:

request.classBitem ?? request.classCitem as IFoo

同样,我们可以在 IFoorequest.classBitem 的数据类型之间进行选择。有到 IFoo 的转换,因此选择了它。

1还要注意,这意味着第一个示例中的括号是多余的。