我对这个小C#quirk感到有点难过:
给定变量:
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
答案 0 :(得分:67)
这是一个经常被问到的问题。
在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
我们需要能够计算出表达式的类型,而不用知道它被分配给它的内容。输入表达式的信息流 out ,而不是到表达式。
为了计算条件表达式的类型,我们计算出结果的类型和替代表达式,选择两种类型中更一般的类型,并且它成为条件表达式的类型。所以在你的例子中,条件表达式的类型是“int”,它不是常量(除非条件表达式是常量true或常量false)。由于它不是常量,因此不能将其分配给字节;当结果不是常数时,编译器仅仅从类型而不是从值开始。
所有这些规则的例外是lambda表达式,其中类型信息 从上下文流入lambda。获得正确的逻辑非常困难。
答案 1 :(得分:11)
我正在使用VS 2005,因为我可以重现,对于bool&布尔值,但不是真的
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);
所以,是的,似乎三元运算符导致常量将其类型“修复”为整数并禁用隐式类型转换,否则您将从适合较小类型的常量中获取。
答案 2 :(得分:7)
我可能没有给你一个很好的答案,但如果你在很多地方这样做,你可以宣布:
private static readonly Byte valueZero = (byte)0;
private static readonly Byte valueOne = (byte)1;
只是这些变量。如果它是项目的本地,您可以使用const
。
readonly
的编辑: 没有意义 - 这些都不会改变。