4

?: 运算符(C# 参考)

first_expression 和 second_expression 的类型必须相同,或者必须存在从一种类型到另一种类型的隐式转换。

整数文字

如果字面量没有后缀,则它具有可以表示其值的第一种类型:int、uint、long、ulong。

考虑:

var value = test ? (Int64)1 : 0;

0,没有后缀的十进制数字文字将转换为int. int可以隐式转换为Int64. 由于这种转换只发生在一个方向上,我们可以放心返回值将是 Int64。

然而:

var value = test ? (UInt64)1 : 0;

UInt64并且int不能隐式转换为彼此,但此代码编译并运行,结果类型为UInt64.

在什么时候0确定类型?

如果这两种类型可以相互隐式转换,那么您最终会得到这两种类型中的哪一种?(我认为这不会正常发生,但用户生成的类可以实现这种转换。)

先前的研究:
我发现了其他几个标题相似的问题,但它们都与 null 或可为 null 的类型有关。

相关性:这在我的代码中很重要,因为我们会立即将此结果传递给 ByteWriter.Write,并希望以正确的重载结束,从而写入正确的字节数。这些例子当然被大大简化了。

替代语法使结果显式可能是清晰的最佳选择,无论在没有显式转换的情况下实际发生什么:

var value = test ? (UInt64)1 : (UInt64)0;
4

2 回答 2

3

请注意,当数字是编译时常量(文字)时,整数类型之间存在一组隐式转换,而当它们不是常量时,则存在另一组转换。

你有趣的例子是:

var value = test ? (UInt64)1 : 0;

也可以写成:

var value = test ? 1ul : 0;

ul后缀的意思是ulong,即System.UInt64

当使用文字(常量)时,确实存在从int( System.Int32) 到的隐式转换ulong,但仅当该int常量为非负时。它实际上与以下内容相同:

const ulong a = 1ul;
const int b = 0;
var value = test ? a : b;  // also works fine

正如我所说,它之所以有效,是因为从int(因为编译器知道b不是负数)到ulong.

现在,拿走const得到:

ulong a = 1ul;
int b = 0;
var value = test ? a : b;  // compile-time error, no implicit conversion in either direction!

我们看到,对于非常数,不存在任何方向的隐式转换,因此没有最佳通用类型aandb并且这失败了。

于 2013-08-28T22:09:29.010 回答
1

没错,泛型 int不能隐式转换为UInt任何长度。但在这里我们不是在谈论通用的、未知的int。我们正在谈论0,它可以转换(甚至在编译时,这是我怀疑编译器正在做的)转换成UInt.

我建议您使用一个int参数(或编译器无法通过数据流分析推断的另一个值),看看会发生什么。

于 2013-08-28T20:24:52.320 回答