在 C# 中,为什么条件运算符不能隐式转换为可为 null 的类型

本文关键字:转换 null 类型 为什么 不能 条件运算符 | 更新日期: 2023-09-27 17:47:21

我很好奇为什么隐式强制转换在...

int? someValue = SomeCondition ? ResultOfSomeCalc() : null;

以及为什么我必须执行显式强制转换

int? someValue = SomeCondition ? ResultofSomeCalc() : (int?)null;

在我看来,编译器拥有做出隐式强制转换决策所需的所有信息,不是吗?

在 C# 中,为什么条件运算符不能隐式转换为可为 null 的类型

C# 3.0 规范的相关部分是 7.13,条件运算符:

?: 运算符的第二个和第三个操作数控制条件表达式的类型。设 X 和 Y 是第二个和第三个操作数的类型。然后

如果 X 和 Y 是相同的类型,则这是条件的类型否则,如果存在从 X 到 Y 的隐式转换 (§6.1),但不存在从 Y 到 X 的隐式转换,则 Y 是条件表达式的类型。否则,如果存在从 Y 到 X 的隐式转换 (§6.1),但不存在从 X 到 Y 的隐式转换,则 X 是条件表达式的类型。否则,无法确定表达式类型,并发生编译时错误。

我也对

它无法根据赋值推断类型感到恼火,尤其是当它是值类型时。 不过,当您进入对象层次结构时,还是有原因的。

如果"ResultOfSomeCalc()"返回一个"int?",那么这将起作用。 C# 需要确定类型,而不考虑赋值左侧的内容。 所以你告诉它你将返回一个 null 或一个 int - 并且编译器中的逻辑不存在让它替换一个 Nullable 作为公分母。

请注意,这些变体确实有效,它可以帮助您了解:

object someValue = true ? new Nullable<int>(ResultOfSomeCalc()) : null;
object someValue = true ? (int?)ResultOfSomeCalc() : null;

希望这有帮助。

这似乎是编译器应该能够自己弄清楚的事情,但是还有另一种方法可以做到这一点,使用默认关键字。 它可能比演员阵容少一点丑陋:

int? someValue = SomeCondition ? ResultofSomeCalc() : default(int?);

这种默认的使用似乎没有很好的记录,但确实有效。 至少它可以防止你用魔术值乱扔代码(我认为null/zero/false/etc.确实是魔术值)。

参见 为什么此代码在 C# 中无效?

如果你的函数 ResultofSomeCalc() 返回 int?,那么这将起作用。

如果您的函数返回 int,则编译器会发出警告: 无法确定条件表达式的类型,因为"int"和"
"之间没有隐式转换我猜这就是你所看到的。 条件运算符 "?:" 中的两个表达式必须具有相同的类型,或者必须可以通过隐式强制转换转换为相同的类型。

将 ResultOfSomeCalc 的返回类型更改为 int?,否则需要在 null 表达式上进行强制转换。

将函数 ResultOfSomeCalc() 的返回类型设为 nullabel int like (int?)
国际?someValue =(int?某种条件 ?ResultofSomeCalc() : (int?)零;