c# - utilizar - ¿Por qué la inicialización de matriz siempre recurre a int?
random next (5)
Lectura de todas las sintaxis posibles de inicialización de matrices C # Me pregunté por qué C # infiere siempre una matriz de int/Int32
donde bastaría un tipo de datos más pequeño, como byte
o short
.
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[]
En la pregunta a la que se hace referencia, Eric Lippert afirma que se usa el "mejor tipo", ver a continuación, pero ¿cómo es el mejor tipo posible? Si vamos por overkill, ¿por qué no usar long
entonces?
El tipo del elemento de la matriz se deduce calculando el mejor tipo, si hay uno, de todos los elementos dados que tienen tipos. Todos los elementos deben ser implícitamente convertibles a ese tipo.
Sospecho que el procesamiento de los tipos de datos de 8 o 16 bits podría ser más rápido que las estructuras de 32 bits, por ejemplo, cuando se utiliza SIMD donde caben instancias de cuatro byte
en el espacio de registro de una int/Int32
. Sé que el compilador JIT no usa (ampliamente) las instrucciones SSE , pero este uso de '' int
everywhere'' asegura que no ayudará mucho cuando el compilador JIT incluya tales optimizaciones.
¿Podría alguien explicar estos hechos y decir por qué siempre recurre a int
?
// Edit // Realmente no me importa la especificación que prescribe que un literal sin un prefijo debe considerarse un int
. Para reformular la pregunta:
¿Por qué se usan tipos de datos que son más grandes de lo necesario? ¿Por qué la especificación tiene esta regla para los literales? ¿Cuáles son las ventajas ya que la gran desventaja es la optimización del futuro (SIMD)?
¿Por qué se usan tipos de datos que son más grandes de lo necesario?
La cantidad de aplicaciones de la línea de negocio en las que realiza un cálculo en números enteros y puede garantizar que el resultado se ajuste en un byte o en un corto es muy pequeña. La cantidad de aplicaciones de línea de negocio en las que el resultado de un cálculo de números enteros se ajusta a una int es enorme .
¿Por qué la especificación tiene esta regla para los literales?
Porque es una regla perfectamente sensata. Es consistente, claro y comprensible. Constituye un buen compromiso entre muchos objetivos de lenguaje, como el rendimiento razonable, la interoperabilidad con el código no gestionado existente, la familiaridad con los usuarios de otros idiomas y el tratamiento de números como números en lugar de patrones de bits. La gran mayoría de los programas C # usan números como números.
¿Cuáles son las ventajas ya que la gran desventaja es la optimización del futuro (SIMD)?
Te aseguro que ni un programador de C # de cada mil mostraría la "dificultad de aprovechar las optimizaciones de SIMD" como una "gran desventaja" de la semántica de inferencia del tipo de matriz de C #. De hecho, puede ser el único. Ciertamente no se me habría ocurrido. Si eres el tipo de persona a la que le importa tanto, haz que el tipo se manifieste en el inicializador de matriz .
C # no fue diseñado para extraer hasta el último gramo de rendimiento de las máquinas que podrían inventarse en el futuro , y particularmente no fue diseñado para hacerlo cuando se trata de la inferencia de tipo. Fue diseñado para aumentar la productividad de los desarrolladores de líneas de negocios, y los desarrolladores de líneas de negocios no piensan en columnWidths = new [] { 10, 20, 30 };
como una matriz de bytes .
C # 5.0 especificación 2.4.4.2
• Si el literal no tiene sufijo, tiene el primero de estos tipos en que se puede representar su valor: int, uint, long, ulong.
• Si el literal tiene el sufijo U o u, tiene el primero de estos tipos en que se puede representar su valor: uint, ulong.
• Si el literal tiene el sufijo L o l, tiene el primero de estos tipos en que se puede representar su valor: long, ulong.
• Si el literal tiene el sufijo UL, UL, UL, UL, LU, LU, LU o LU, es de tipo ulong.
Todos sus ejemplos tocan el primero en esa lista ... int
.
Todos los literales integrales siguen esta regla. Por eso var i = 10;
se infiere como int
también.
Creo que las operaciones siempre serán más rápidas en el tamaño de bit nativo, por lo que int
para máquinas de 32 bits, de ahí la convención.
Esto también implica que para ejecutar aplicaciones de 64 bits, int64 se usaría mejor que int para matrices.
Cuando se pone un valor entero sin ningún sufijo como 30, 130, 230
declaras el valor int32 ; asi que
new[] { 30, 130, 230 }; // <- array of int''s
y si quieres una matriz de bytes, debes ponerlo explícitamente :
new byte[] { 30, 130, 230 }; // <- treat each value as byte
Los literales que usa como ejemplos tienen todos System.Int32
, mientras que los valores pueden almacenarse sin pérdida en tipos System.Int16
reducidos (por ejemplo, System.Int16
), la sintaxis dice System.Int32
.
Como todos los miembros especificados de cada matriz son System.Int32
, la matriz tiene el tipo System.Int32[]
.
Por supuesto, sería posible definir un lenguaje donde los literales integrales (sin otras indicaciones como sufijos) tengan el tipo "el tipo integral más pequeño suficiente para contener el valor" de que el lenguaje no es C #.
En la última especificación del lenguaje V5.0 - C # (de mi instalación VS2013), en la sección 2.4.4.2:
Los literales enteros se utilizan para escribir valores de los tipos
int
,uint
,long
yulong
.
Es decir. no hay forma de escribir un byte
, sbyte
, short
o unsigned short
literal sin un molde.