61

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

给定变量:

Boolean aBoolValue;
Byte aByteValue;

以下编译:

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

但这不会:

aByteValue = aBoolValue ? 1 : 0;

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

当然,这个怪物会编译:

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

这里发生了什么?

编辑:

使用 VS2008,C# 3.5

4

3 回答 3

69

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

在 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”,它不是一个常量(除非条件表达式是常量真或常量假)。由于它不是常量,因此不能将其分配给字节;当结果不是常量时,编译器仅根据类型而非值进行推理。

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

于 2010-02-07T04:39:15.510 回答
12

我正在使用 VS 2005,对于 bool 和 Boolean,我可以重现,但不是真的

 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);

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

于 2010-02-07T03:25:15.817 回答
7

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

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

以及这些变量。const如果它是项目本地的,您可能会逃脱使用。

编辑:使用readonly没有意义 - 这些永远不会改变。

于 2010-02-07T03:16:58.253 回答