关于c#:条件运算符不能隐式转换?

Conditional operator cannot cast implicitly?

我有点被这个小怪癖难住了:

给定变量:

1
2
Boolean aBoolValue;
Byte aByteValue;

以下汇编:

1
2
3
4
if (aBoolValue)
    aByteValue = 1;
else
    aByteValue = 0;

但这不会:

1
aByteValue = aBoolValue ? 1 : 0;

错误说明:"无法将类型"int"隐式转换为"byte"。

当然,这个怪物会编译:

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

这是怎么回事?

编辑:

使用VS2008,c 3.5


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

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

1
x = y;

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

这是因为可能有多个X:

1
2
3
4
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)。因为它不是常量,所以不能将其赋给byte;当结果不是常量时,编译器只根据类型而不是值进行推理。

所有这些规则的例外是lambda表达式,其中类型信息确实从上下文流入lambda。要把逻辑搞好是非常困难的。


我使用的是VS2005,因为我可以为布尔型(bool&boolean)复制,但不是真的。

1
2
3
4
5
 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 ;)

最简单的解决方法似乎是

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

因此,是的,三元运算符似乎导致常量"固定"它们的类型为int,并禁用隐式类型转换,否则您将从适合较小类型的常量中获得这种转换。


我对你的回答也许不是很好,但如果你在许多地方这样做,你可以声明:

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

只有这些变量。如果const是项目本地的,那么您可能不需要使用它。

编辑:使用readonly是没有意义的-这些从来没有打算改变。