为什么数组初始化总是采用int类型?

4

阅读所有可能的C#数组初始化语法,我想知道为什么C#总是推断出一个int / Int32数组,而更小的数据类型,如byteshort也可以胜任。

new[] { 30, 130, 230 } // sbyte[] suffices but becomes int[]
new[] { -1, 125, -119 } // sbyte[] suffices  but becomes int[]
new[] { -31647, -1337, 23456} // short suffices but becomes int[]

在所引用的问题中,Eric Lippert指出使用“最佳类型”,如下所示,但是为什么int是最好的可能类型呢?如果我们选择过度设计,为什么不使用long呢?
引用块:
阵列元素的类型通过计算给定具有类型的所有元素的最佳类型(如果有)来推断。 所有元素必须可以隐式转换为该类型。
我猜处理8位或16位数据类型比32位结构更快,例如在使用SIMD时,其中四个byte实例可以适合一个int/Int32的寄存器空间中。 我知道JIT编译器不(广泛地)使用SSE指令,但是这种“到处都用int”的用法确保当JIT编译器要包含这样的优化时,它将不会帮助太多。
能否有人详细说明这些事实,并告诉为什么总是倾向于使用int
//编辑// 我并不关心规范,规定没有前缀的文字应被视为int。重新phrase一下问题:
为什么使用大于所需的数据类型?规范为什么有这个字面的规则?有什么优点,因为巨大的缺点是远离未来(SIMD)优化。

2
我猜这里与Java无关。 - Rohit Jain
我认为在32位机器上,32位结构比其他类型的结构更快。 - Rafa
如果我们要过度设计 => 我们不会,通常操作int32比操作int8/int16更快。 - ken2k
@RohitJain - 感谢您的澄清,我已经编辑了我的帖子,删除了对Java的引用 - 不仅是关键字 :) - M. Mimpen
什么是缺点?在声明数组时明确指定类型有什么阻碍吗?坦白说,我不理解你的问题。 - InBetween
5个回答

6
为什么要使用比所需更大的数据类型?
您在整数计算中可以保证结果适合字节或短整型的业务应用程序数量极少。而整数计算结果适合int的业务应用程序数量则非常庞大。
为什么规范要求这种文本格式?
因为这是一个非常合理的规则,一致、明确且易于理解。它在许多语言目标之间取得了很好的平衡,例如合理的性能、与现有非托管代码的互操作性、对其他语言用户的熟悉程度以及将数字视为“数字”而不是位模式等。绝大多数C#程序将数字用作数字。
优点是什么,既然巨大的缺点是远离未来(SIMD)优化?
我向您保证,在C#的数组类型推断语义方面,不会有一个C#程序员将“难以利用SIMD优化”列为“巨大的缺点”。实际上,您可能是唯一一个这样想的人。这当然没能引起我的注意。如果您是那种非常关注此问题的人,则可以在数组初始化器中显示声明类型。
C#的设计目标不是为了从“未来可能发明的计算机”中挤出每一分性能,特别是涉及到类型推断时更不是如此。它的目标是提高业务应用程序开发人员的生产力,而业务应用程序开发人员不会将columnWidths = new [] { 10, 20, 30 };视为一个字节数组。

4

C# 5.0规范2.4.4.2

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

• 如果字面量带有U或u后缀,则它具有可以表示其值的类型中的第一个:uint或ulong。

• 如果字面量带有L或l后缀,则它具有可以表示其值的类型中的第一个:long或ulong。

• 如果字面量带有UL、Ul、uL、ul、LU、Lu、lU或lu后缀,则它是ulong类型。

所有示例都符合此列表中的第一项... int

所有整数字面量都遵循此规则。这就是为什么var i = 10;也被推断为int


谢谢您的快速回答,但由于我不是在寻找如何处理文字,所以我澄清了问题。 - M. Mimpen
1
根据您的编辑,您的问题是为什么规范对字面量有这个规则? - Simon Whitehead
是的,完全正确。看来我很难找到正确的问题。 - M. Mimpen
1
需要更深入的了解才能回答这个问题。但是,我有一种感觉,那就是因为CLR中的算术运算实际上并不是在小于32位的任何东西上执行的。比32位小的任何东西都会被提升,以便操作坐落在平台的字大小边界上。通过推断32位作为默认值...您可以避免(毫无疑问...相当小的)提升成本。 - Simon Whitehead

1
当你输入没有任何后缀的整数值,比如 30, 130, 230,你声明了一个 int32 类型的值;因此
new[] { 30, 130, 230 }; // <- array of int's

如果您想要字节数组,您需要明确地将其放入:

  new byte[] { 30, 130, 230 }; // <- treat each value as byte

1
你所使用的示例文本中所有的字面值都有System.Int32,虽然这些值可以在缩小的整数类型(例如System.Int16)中存储而不会丢失,但语法却指定为System.Int32
由于每个数组的指定成员都是System.Int32,因此该数组的类型为System.Int32[]
当然,可以定义一种语言,其中整数字面量(没有后缀等其他指示)具有“足以容纳该值的最小整数类型”的类型,但该语言不是C#。
在最新的-V5.0-C#语言规范(来自我的VS2013安装)中,在第2.4.4.2节中:

用于编写intuintlongulong类型的值的整数字面量。

也就是说,没有办法编写一个bytesbyteshortunsigned short字面量而不需要强制转换。

和 @Simon 一样,规范是一回事,但为什么语言没有像您所描述的那样制定“足以容纳该值的最小整数类型”呢? - M. Mimpen
@M.Mimpen 因为这是设计师决定的。你需要问问他们,除非他们在某个地方写了一份理由(但我认为他们没有)。 - Richard

-2

我相信在本机位大小下运行操作始终会更快,因此对于32位机器使用int是惯例。

这也意味着对于运行64位应用程序,使用int64而不是int更好地用于数组。


听起来合理,但你有没有证据表明在64位机器上使用int64进行int32操作? - M. Mimpen
啊,不好意思,我的意思是如果你将数字明确声明为int64,那么对于你的程序来说会更好 - 在C#中,int始终表示int32。 - Starscream1984
1
Sriram - 我认为当时机器的标准位数可能与C#设计者最初选择int32作为其“默认” int位数有关。 - Starscream1984

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接