条件运算符不能隐式转换?

我有点难住这个小小的C#怪癖:

给定变量:

Boolean aBoolValue; Byte aByteValue; 

以下编译:

 if (aBoolValue) aByteValue = 1; else aByteValue = 0; 

但是这不会:

 aByteValue = aBoolValue ? 1 : 0; 

错误说:“不能隐式地将类型'int'转换为'字节'”。

当然,这个怪物会编译成:

 aByteValue = aBoolValue ? (byte)1 : (byte)0; 

这里发生了什么?

编辑:

使用VS2008,C#3.5

这是一个相当常见的问题。

在C#中,我们几乎总是从内部到外部推理。 当你看到

 x = y; 

我们计算x的类型是什么,y的类型是什么,以及y的类型是否与x兼容。 但是当我们计算出y的类型时,我们并不使用这个事实,即我们知道x的类型是什么。

那是因为可能有多个x:

 void M(int x) { } void M(string x) { } ... M(y); // y is assigned to either int x or string x depending on the type of y 

我们需要能够计算表达式的类型, 而不必知道它被分配了什么。 类型信息流出表达式,而不是表达式。

为了计算条件表达式的类型,我们计算出结果类型和替代表达式,选择两个类型中更一般的,并且成为条件表达式的类型。 所以在你的例子中,条件表达式的类型是“int”,它不是一个常量(除非条件表达式是常量true或常量false)。 既然它不是一个常量,你不能把它分配给字节; 当结果不是一个常量时,编译器只能从类型中得到原因,而不能从值中得出结论。

所有这些规则的例外是lambda表达式,其中类型信息从上下文流入lambda。 正确理解这个逻辑非常困难。

我正在使用VS 2005,因为我可以重现,布尔和布尔,但不是真实的

  bool abool = true; Boolean aboolean = true; Byte by1 = (abool ? 1 : 2); //Cannot implicitly convert type 'int' to 'byte' Byte by2 = (aboolean ? 1 : 2); //Cannot implicitly convert type 'int' to 'byte' Byte by3 = (true ? 1 : 2); //Warning: unreachable code ;) 

最简单的解决办法似乎是这个演员

  Byte by1 = (Byte)(aboolean ? 1 : 2); 

所以,是的,似乎三元运算符正在导致常量“固定”他们的类型作为整数,并禁用隐式类型转换,否则你会从适合的较小类型的常量中获得。

我可能没有一个很好的答案,但如果你在很多地方做这个,你可以声明:

 private static readonly Byte valueZero = (byte)0; private static readonly Byte valueOne = (byte)1; 

只是这些变量。 如果它是本地项目,您可能会使用const

编辑:使用readonly将没有任何意义 – 这些都不是要改变。