【问题标题】:Why does null need an explicit type cast here? [duplicate]为什么 null 在这里需要显式类型转换? [复制]
【发布时间】:2011-02-06 05:21:26
【问题描述】:

以下代码无法编译:

//int a = ...
int? b = (int?) (a != 0 ? a : null);

为了编译,需要改成

int? b = (a != 0 ? a : (int?) null);

由于b = nullb = a 都是合法的,这对我来说没有意义。

为什么我们必须将null 转换为int?,为什么我们不能简单地为整个表达式提供一个显式类型转换(我知道在其他情况下也可以)?

【问题讨论】:

  • 我只是觉得编译器不喜欢你问这么多问题。我的意思是看,你在一行中有 3 个!
  • 这应该回答你的问题,为什么:stackoverflow.com/questions/2215745/…。这个问题与那个问题相当重复,但推理仍然相同。
  • 请注意int? b = a != 0 ? (int?)a : null; 也可以使用

标签: c# .net casting null


【解决方案1】:

来自 C# 语言规范的第 7.13 章:

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

  • 如果 X 和 Y 是同一类型,则这是条件表达式的类型。
  • 否则,如果存在从 X 到 Y 而不是从 Y 到 X 的隐式转换(第 6.1 节),则 Y 是条件表达式的类型。
  • 否则,如果存在从 Y 到 X 而不是从 X 到 Y 的隐式转换(第 6.1 节),则 X 是条件表达式的类型。
  • 否则无法确定表达式类型,并出现编译时错误。

在您的情况下,没有从 int 到 null 的隐式转换,也没有相反的方式。你的演员解决了这个问题,int 可以转换为 int 吗?

【讨论】:

  • 啊,我明白了。不过,我认为这两个表达式不需要具有相同的类型,只要它们都隐式转换为分配的类型 - 如果我说 Animal animal = (condition ? new Cat() : new Dog()) 会发生什么?
  • 那么你也会得到一个编译器错误。 (除非你将任何一方投给Animal
  • 赋值语句的左侧不影响表达式的类型。我妻子坚持认为,猫并不能隐含地变成狗。
  • 我希望未来的 C# 版本会使用更智能的类型推断。 C# 在调用泛型方法“T M(T a, T b)”时已经可以做到这一点,那么为什么不使用“c?a:b”呢?
  • 当您可以在 int 和 null 之间进行选择时,您会推断出什么类型?如果你说“int?当然!”那么当表达式分配给一个int时你会怎么做。你会让它在运行时轰炸吗?使用在任何地方都不可见的隐藏类型不是 C# 方式。
【解决方案2】:

这几乎是我的问题one 的重复,关于条件运算符。不是空值,真的是:

那里接受的答案非常好,来自 C# 编译器团队的 Eric Lippert。

【讨论】:

    【解决方案3】:

    如果您使用default(int?) 而不是null,您可以免于投射。

    int a = 42;
    int? b = (a != 0 ? a : default(int?));
    

    【讨论】:

      【解决方案4】:

      当你对不同类型的操作数使用条件运算符时,编译器会检查其中一种类型是否可以隐式转换为另一种类型。

      如果两种类型都不能隐式转换为另一种,则会出错,即使它们都可以隐式转换为第三种类型。编译器不会同时在两边插入隐式转换。

      在您的情况下,intnull 都需要隐式转换才能变为 int?,因此它不起作用。
      您需要更改代码,以便一侧是int?,而另一侧可以隐式转换为int?。最简单的方法是将null 替换为new int?(),如下所示:

      int? b = (a != 0 ? a : new int?());
      

      这只需要一次隐式转换(intint?)。

      【讨论】:

        【解决方案5】:

        ?: 运算符的两个替代项必须属于同一类型。 否则编译器无法推断出整个条件表达式的类型。

        null 不是int,因此需要提示编译器生成的类型是int?


        编辑:正如其他人指出的那样,这两种类型不需要相同,但其中一种应该可以转换为另一种(另一种将是结果类型)。详情请见specs

        【讨论】:

          【解决方案6】:

          这是因为当你使用这种表示法时,两个成员必须是同一类型,所以你必须明确地说“这个成员是一个 int?”。

          清楚了吗?

          【讨论】:

          • -1:它们不需要是同一类型,只需要可转换为另一个类型即可:见上文,@nobugz 和 @Vlad。
          • @srpt,我也想投反对票,但后来我看到你并没有真正投反对票,所以取消了我的投反对票。
          • =/ 我什么? [单片眼镜弹出] 诅咒!我取消了反对票,因为我改变了主意,但忘记在评论开头编辑-1: - 请原谅! (我改变了主意,因为这不是一个错误的答案,只是不是很准确或清楚。)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多