条件运算符不能隐式转换?
我有点难住这个小小的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
将没有任何意义 – 这些都不是要改变。