2011-12-29 9 views
9

Por ejemplo, ¿por qué long int tiene un modificador literal, pero short int no? Me refiero a la siguiente pregunta en este sitio: C# compiler number literalsPor qué algunos tipos no tienen modificadores literales

En general, C# parece ser un lenguaje muy bien diseñado y consistente. Probablemente haya una buena razón para proporcionar modificadores literales para algunos tipos, pero no para todos. ¿Qué es?

+1

Eche un vistazo a esta pregunta (y la respuesta de Eric Lippert): http://stackoverflow.com/questions/1678591/why-are-number-suffixes-necessary –

Respuesta

35

¿Por qué long int tiene un modificador literal, pero short int no?

La pregunta es "¿por qué C# no tiene esta función?" La respuesta a esa pregunta es siempre la misma. Las características no se implementan por defecto; C# no tiene esa característica porque nadie diseñó, implementó y envió la característica a los clientes.

La ausencia de una característica no necesita justificación. Por el contrario, todas las características deben justificarse mostrando que sus beneficios superan sus costos. Como persona que propone la función, usted tiene la responsabilidad de describir por qué cree que la característica es valiosa; no me corresponde a mí explicar por qué no lo es.

Probablemente hay una fuerte razón para proporcionar modificadores literales para algunos tipos, pero no para todos. ¿Qué es?

Ahora que es una pregunta más respondible. Ahora la pregunta es "¿qué justifica el sufijo literal a largo, y por qué no es también una justificación para un sufijo literal similar en abreviatura?"

enteros se pueden utilizar para una variedad de propósitos. Puede usarlos como números aritméticos. Puede usarlos como colecciones de indicadores de bit. Puede usarlos como índices en matrices. Y hay muchos usos más especiales. Pero creo que es justo decir que la mayoría de las veces, los enteros se usan como números aritméticos.

La gran mayoría de los cálculos realizados en números enteros por programas normales implican números que son mucho, mucho menores que el rango de un entero de 32 bits con signo, aproximadamente +/- dos mil millones. Y un montón de hardware moderno es extremadamente eficiente cuando se trata únicamente de enteros de 32 bits. Por lo tanto, tiene sentido hacer que la representación por defecto de los números tenga enteros de 32 bits. C# está por lo tanto diseñado para hacer que los cálculos que involucran enteros de 32 bits se vean perfectamente normales; cuando dice "x = x + 1", se entiende que "1" es un entero de 32 bits con signo, y las probabilidades son buenas de que x también lo es, y el resultado de la suma también lo es.

¿Qué ocurre si el cálculo es integral pero no encaja en el rango de un entero de 32 bits?los enteros "largos" de 64 bits son un siguiente paso lógico; también son eficientes en una gran cantidad de hardware y longs tienen un rango que debe satisfacer las necesidades de prácticamente cualquier persona que no está haciendo combinatoria de servicio pesado que involucran números extremadamente grandes. Por lo tanto, tiene sentido tener alguna forma de especificar clara y concisamente en el código fuente que este literal aquí debe tratarse como un entero largo.

Escenarios de interoperabilidad, o escenarios en los que los enteros se utilizan como campos de bits, a menudo requieren el uso de enteros sin signo. De nuevo, tiene sentido tener una forma de especificar clara y concisamente que este literal está destinado a tratarse como un entero sin signo.

Por lo tanto, en resumen, cuando vea "1", es probable que la mayoría de las veces el usuario intente utilizarlo como un entero de 32 bits con signo. Los siguientes casos más probables son que el usuario tiene la intención de que sea un entero largo o un int sin firmar o unsigned long. Por lo tanto, hay sufijos concisos para cada uno de esos casos.

Por lo tanto, la función está justificada.

¿Por qué no es una justificación para los pantalones cortos?

Porque en primer lugar, en todos los contextos en que un breve es legal, ya es legal usar un literal entero. "corto x = 1;" es perfectamente legal; el compilador se da cuenta de que el entero se ajusta a un breve y le permite usarlo.

En segundo lugar, aritmética nunca se hace en pantalones cortos en C#. La aritmética se puede hacer en ints, uints, longs y ulongs, pero la aritmética es nunca hecha en cortocircuitos. Los cortos se promocionan a int y la aritmética se realiza en ints, porque como dije antes, la gran mayoría de los cálculos aritméticos se ajustan a un int. La gran mayoría hace no encaja en un corto. La aritmética breve es posiblemente más lenta en hardware moderno que está optimizado para ints, y la aritmética corta no ocupa menos espacio; se va a hacer en ints o longs en el chip.

Quiere un sufijo "largo" para decirle al compilador "esta aritmética debe hacerse en largos" pero un sufijo "corto" no le dice al compilador "esta aritmética debe hacerse en cortocircuitos" porque eso es simplemente no es una característica del lenguaje C# para empezar.

Las razones para proporcionar un sufijo largo y una sintaxis sin signo no se aplican a los cortos. Si cree que hay un beneficio convincente para la función, indique cuál es el beneficio. Sin un beneficio que justifique sus costos, la función no se implementará en C#.

+1

consistencia debe ser una justificación lo suficientemente fuerte, ¿no es así? Sin embargo, esta incoherencia parece estar ahí por una razón: me advierte de los costos de la conversión a int y de regreso a corto cada vez que necesito hacer algo con mi short. –

+0

@Lund: casi no hay ningún costo asociado con la conversión, a menos que se use una aritmética comprobada. La aritmética se realiza en registros de la CPU que siempre tienen al menos 32 bits de ancho. La carga de la memoria y las instrucciones de la tienda realmente hacen las conversiones, y pueden variar ligeramente en el conteo cíclico. Sin embargo, la utilización de la memoria caché con frecuencia compensa con creces cualquier pérdida, lo que puede hacer que el rendimiento general con el uso de cortos sea mejor que el uso de ints. –

+3

@KevinCathcart: siempre que los pantalones cortos estén bien embalados. Una serie de cortos, por ejemplo, puede dar como resultado menos errores de caché que una serie de entradas. Pero a menudo veo personas que declaran * variables locales * como cortas porque creen que hacerlo es "guardar dos bytes de memoria", lo cual no tiene sentido. –

1

Si declara un literal corto y lo hace más grande que Short.MaxValue se producirá un error del compilador, de lo contrario, el literal será breve.

+1

Un literal puede ser largo, como 1L. Aparentemente, no hay tal cosa como un breve literal. –

+1

@BasB: Esto no es del todo correcto: puede declarar una variable o una constante que es 'corta', pero tiene que inicializarla con un literal no corto; la verificación de rango está hecha, como usted nota, por el compilador. La especificación de C# (4.0) define literales en la sección 2.4.4, y, de literales enteros, dice que "se usan para escribir valores de tipos' int', 'uint',' long', y 'ulong'." – phoog

2

Desde un short se puede convertir implícitamente a int, long, float, double, o decimal; no hay necesidad de un modificador literal.

considerar:

void method(int a) {} 
void method2() 
{ 
    short a = 4; 
    method(a); // no problems 
} 

puede observar que char y byte son también con modificadores literales, para posiblemente esta misma razón.

From To 
sbyte short, int, long, float, double, or decimal 
byte short, ushort, int, uint, long, ulong, float, double, or decimal 
short int, long, float, double, or decimal 
ushort int, uint, long, ulong, float, double, or decimal 
int  long, float, double, or decimal 
uint long, ulong, float, double, or decimal 
long float, double, or decimal 
char ushort, int, uint, long, ulong, float, double, or decimal 
float double 
ulong float, double, or decimal 
+4

Su método2 demostró la conversión 'short' =>' int', esa es la otra dirección que en 'short s = 1;' –

9

Según MSDN:

short x = 32767; 

En la declaración anterior, el número entero literal 32767 es implícitamente convertido de int a corto. Si el literal entero no cabe en en una ubicación de almacenamiento corta, se producirá un error de compilación.

Es una función de tiempo de compilación. short no tiene un sufijo porque nunca sería necesario.

La pregunta relacionada probablemente sea: ¿Por qué long, float y decimal tienen sufijos?
Y una respuesta corta sería que i + 1 y i + 1L pueden producir valores diferentes y, por lo tanto, son de tipos diferentes.

Pero no existe tal cosa como 'aritmética corta', los valores de short siempre se convierten a int cuando se usan en un cálculo.

+0

Henk, me gustó su escritura. Es una pena no puedo aceptar dos respuestas. –

4

Como Eric señala en el comentario, mi respuesta a continuación no tiene sentido. Creo que es más correcto decir que la incapacidad de expresar un breve literal en C# y la incapacidad de expresar un breve literal en IL comparten una causa común (la falta de un motivo convincente para la función). VB.Net aparentemente tiene un corto el especificador literal, que es interesante (¿por compatibilidad con la sintaxis de VB?) En cualquier caso, he dejado la respuesta aquí ya que parte de la información puede ser interesante, incluso si el razonamiento es incorrecto.


No hay resumen literal porque no hay realmente ninguna manera por un corto literal para ser cargado en IL, el lenguaje subyacente utilizado por el CLR. Esto se debe a que todos los tipos 'cortos' (cualquier cosa más pequeña que un int) se amplían implícitamente a un int cuando se cargan en la pila de operaciones. Firmado y sin firmar son también una cuestión de operaciones y no están 'almacenados' con el número activo en la pila de operaciones.Los tipos 'cortos' solo entran en juego cuando quiere almacenar un número en la pila de operaciones en una ubicación de memoria, por lo que hay operaciones IL para Convertir a varios tipos 'cortos' (aunque en realidad todavía amplía el número a una int después de la conversión, solo se asegura de que el valor sea adecuado para almacenar en un campo del tipo 'corto').

Los tipos largos tienen un especificador literal, por otro lado, debido a que son tratado de manera diferente en la pila de operaciones. Hay una instrucción Ldc_I8 separada para cargar valores largos constantes. También hay Ldc_R4 (de ahí por qué necesita 'f' para flotar) y Ldc_R8 (C# elige esto como predeterminado si usa un número decimal sin especificador). Decimal es un caso especial, ya que no es en realidad un tipo primitivo en IL ; solo tiene un especificador de constante constante 'm' en C# que compila a una llamada de constructor.

En cuanto a por qué no hay operaciones cortas especiales (y literales cortos correspondientes), es probable porque la mayoría de las arquitecturas de CPU actuales no funcionan con registros menores de 32 bits, por lo que no hay diferencia en el nivel de CPU que valga la pena explotar. Podría potencialmente guardar el tamaño del código (en términos de bytes de IL) al permitir códigos de carga IL 'cortos', pero a costa de una complejidad adicional para el jitter; el espacio de código guardado probablemente no valga la pena.

+0

("potencialmente podría guardar el tamaño del código ...") - Pero * hay * códigos de operación "cortos", para guardar bytes de IL (lo que significa que el código CIL es corto, no necesariamente que se refieran al tipo de datos 'corto') Por ejemplo, uno incluso existe para i4 (cuatro bytes de bytes): 'ldc.i4.s' toma un argumento de un byte y lo inserta en la pila como int32. De la especificación: "Hay codificaciones cortas especiales para los enteros -128 a 127 (con codificaciones especialmente cortas para -1 a 8)". – phoog

+4

Esta respuesta no tiene ningún sentido. El error fundamental está en la primera oración. Si la razón por la cual la característica no está en C# es porque C# compila a IL, ¿por qué la característica en otros idiomas compila a IL? –

0

El tiempo que he "trabajado en corto" fue para valores que están almacenados en una base de datos.

Son valores enteros positivos que rara vez pasarán de 10 a 20. (Un byte o sbyte sería lo suficientemente grande, pero pensé que un poco más de matar me evitaría lamentar mi elección, si el código se reutilizara en un forma ligeramente diferente)

El campo se utiliza para permitir al usuario ordenar los registros en una tabla. Esta tabla contiene un menú desplegable o una lista de botones de opción ordenados por "tiempo" (paso uno, paso dos, ...).

Ser nuevo en C# (y lo suficientemente viejo como para recordar cuando el conteo de bytes era importante) pensé que sería un poco más eficiente. No hago matemáticas en los valores. Simplemente los clasifico (y los cambio entre registros). La única matemática hasta ahora ha sido "MaxInUse" +1 (para nuevos registros), que es un caso especial "++ MaxInUse".Esto es bueno, porque la falta de un literal significa "s = s + 2" tendría que ser "s = (Int16) (s + 2)".

Ahora que veo cómo el molesto C# hace que funcione con las otras versiones, espero unirme al mundo moderno y perder bytes, SOLO para hacer feliz al compilador.

Pero, ¿no debería el ranking "hacer feliz al compilador" sobre el # 65 en nuestros 10 mejores objetivos de programación?

¿Alguna vez es una ventaja que el compilador se queje de agregar el entero "2" a CUALQUIERA de los tipos INTEGER? Debería quejarse de "s = 123456", pero ese es un caso diferente.

Si alguien tiene que lidiar con los pantalones cortos de matemáticas Y, le sugiero que cree sus propios literales. (¿Cuántas se puede pedir?)

short s1= 1, s2 = 2, s123 = 123; 

entonces S = s + S2 es sólo un poco molesto (y confuso para los que siguen después).

+0

Tengo que pensar, debería probar, en lugar de simplemente despegar una buena idea. s = s + s2; Otorga el mismo error que s = s + 2. El compilador de C# es tan molesto por ser fuertemente tipado, un Corto + un Corto produce un Int. Esta puede ser la razón por la cual varias personas afirmaron que todas las matemáticas se hacen como Ints. Basado en esta prueba, propongo una respuesta a la pregunta original. No existe un breve literal, porque nunca sería útil. Incluso si tuviera uno, no puede agregar 2 Shorts y ponerlo en otro Short. (Esto me lleva de vuelta en un círculo para preguntar POR QUÉ, pero, eso es por otro día). –

Cuestiones relacionadas