为何使用null合并运算符的赋值语句无法编译?
为什么
Foo? ?? Bar?无法编译,而显式转换或if语句可以? 问题核心:??运算符的类型推断规则
C# 的 ??(空合并运算符)对操作数的类型有严格要求:它需要两个操作数能够隐式转换到同一个公共类型,并且编译器会优先寻找最具体的公共类型,而非直接 fallback 到顶层的 object。
在你的代码中:
Foo? foo = null; Bar? bar = new Bar(); object? val = foo ?? bar; // 编译失败
Foo 和 Bar 是两个无继承关系的独立类,它们没有除 object 之外的更具体公共类型。但编译器不会自动将两个操作数都隐式提升到 object 来满足运算符要求——因为 ?? 的类型推断是基于操作数自身的类型,而非最终赋值的目标类型。
为什么if语句可以正常运行?
if分支中的赋值是独立进行的:
object? val = default; if (foo != null) val = foo; // 单独将Foo?隐式转换为object? else val = bar; // 单独将Bar?隐式转换为object?
每个分支的赋值操作是单独处理的,编译器只需要验证单个操作数能否转换到目标类型即可,不需要两个操作数之间有公共类型。
显式转换后为什么能编译?
当你把 foo 显式转换为 object? 后:
object? val = (object?)foo ?? bar;
此时 ?? 的左操作数类型是 object?,而 Bar? 可以隐式转换为 object?,两个操作数的类型兼容,符合运算符的要求,因此可以正常编译。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

