2012-04-18 22 views
52

Dada la siguiente enumeración:¿Por qué debería hacer el tipo subyacente de un Enum Int32 en lugar de un byte?

public enum Operations_PerHourType : byte 
{ 
    Holes = 1, 
    Pieces = 2, 
    Sheets = 3, 
    Strips = 4, 
    Studs = 5 
} 

Cuando ejecuto la herramienta de análisis de código de Microsoft, me dice:

CA1028: Microsoft.Design: Si es posible, hacer que el tipo subyacente de 'enumeraciones. Operations_PerHourType 'System.Int32 en lugar de' byte '.

Nunca tendrá más de un par de valores posibles, por lo que lo declaró como un byte. ¿Por qué recomendarían usar int32? ¿Más valores para una escalabilidad futura? ¿O hay una mejora en el rendimiento?

+5

¿Por qué le importa si el almacenamiento es un byte o un int? ¿Cuál es tu motivación para tratar de forzar el uso de un byte? –

+4

No lo hice, hasta que ejecuté la herramienta de análisis de código de Microsoft. Se recomienda usar un Int32. Tengo curiosidad por qué. Usé byte inicialmente porque supuse que sería mejor para el rendimiento. Menos espacio. – Kevin

+1

http://stackoverflow.com/questions/5005319/why-cant-i-declare-an-enum-inheriting-from-byte-but-i-can-from-byte –

Respuesta

40

Echa un vistazo a MSDN por este motivo.

Aquí es un extracto:

Una enumeración es un tipo de valor que define un conjunto de relacionados con nombre constantes. De forma predeterminada, el tipo de datos System.Int32 se utiliza para almacenar el valor constante . Aunque puede cambiar este tipo subyacente, es no necesario o recomendado para la mayoría de los escenarios. Tenga en cuenta que no se obtiene una ganancia de rendimiento significativa de al usar un tipo de datos que es más pequeño que Int32. Si no puede usar el tipo de datos predeterminado, debe usar uno de los tipos integrales integrales compatibles con el Sistema de lenguaje común (CLS), Byte, Int16, Int32 o Int64 para asegurarse de que todos los valores de puedan representarse en la enumeración Programación CLS-obediente idiomas.

+0

Muchas gracias. – Kevin

21

De acuerdo con la documentación, no se obtiene ganancia de rendimiento al utilizar un byte en lugar de INT32. A menos que haya una razón para hacerlo, recomiendan no cambiarlo. La idea subyacente es que .NET está optimizado para usar INT32 en muchos escenarios, y lo seleccionaron para enumeraciones por una razón. No obtienes nada en tu escenario al cambiarlo, así que, ¿para qué molestarse?

http://msdn.microsoft.com/en-us/library/ms182147.aspx

Esto también habla de cómo .NET está optimizado para utilizar 32 bits enteros: .NET Optimized Int32

+2

No es .NET optimizado para usar INT32, sino la CPU subyacente, sobre todo debido al tamaño/tamaño de registro de los operandos de las instrucciones de ensamblaje, que es de 32 bits en un sistema de 32 bits. Si el tamaño del valor es diferente, debe alinearse/rellenarse y se necesitan ciclos de CPU adicionales para eso. Curiosamente, esto se menciona en el hilo que vinculó. Lo más probable es que la sobrecarga sea mínima. El punto es, sin embargo, que usar BYTE en lugar de INT32 por razones de rendimiento en realidad tendrá el efecto opuesto. Ese es el caso para cada lenguaje HL. –

+1

@SaschaHennig - Ese hilo da un fondo bueno pero incompleto. Lea también este: http://stackoverflow.com/questions/1054657/memory-alignment-on-a-32-bit-intel-processor para saber por qué su enumeración basada en Int32 a veces ocupará hasta 8 bytes en una el diseño de la estructura, y eso es una decisión de doble filo relacionada con el rendimiento de Microsoft que puede anular si sabe lo que está haciendo. No es el marco o el hardware quien está a cargo. Trabajan juntos. –

+0

@Jirka Hanika - lectura interesante, gracias.Cualquier lenguaje HL solo puede optimizar el uso de variables (o cualquier cosa realmente) en el contexto del hardware que se está ejecutando. Todavía no es ni el marco ni el hardware lo que está a cargo, por último, es el codificador. –

21

Hay situaciones específicas en las que el estrechamiento del tipo subyacente trae algunas ventajas, por ejemplo, el rendimiento relacionado o forzar a un particular, diseño de memoria cuando se hace interfaz con código no administrado.

Considere este ejemplo:

using System; 

public enum Operations_PerHourType // : byte 
{ 
    Holes = 1, 
    Pieces = 2, 
    Sheets = 3, 
    Strips = 4, 
    Studs = 5 
} 

class Program 
{ 
    static void Main() 
    { 
     long before = GC.GetTotalMemory(false); 
     var enums = new Operations_PerHourType[10000]; 
     long after = GC.GetTotalMemory(false); 

     Console.WriteLine(after - before); 
     // output (byte): 12218 (I'm using Mono 2.8) 
     // output (Int32): 40960 
    } 
} 

Este código consume aproximadamente 40 KB de la pila. Ahora especifique (descomente) el tipo subyacente como byte y vuelva a compilar. Guau. De repente, solo necesitamos aproximadamente 10 KB.

La compactación de memoria de este tipo a veces puede hacer que un programa sea más lento, no más rápido, dependiendo de los patrones de acceso y tamaños de datos particulares. No hay forma de saber con certeza que hacer algunas mediciones e intentar generalizar a otras posibles circunstancias. El recorrido secuencial de datos más pequeños suele ser más rápido.

Sin embargo, desarrollar el hábito de especificar tipos angostos simplemente porque generalmente es posible y, a veces, crucial, no es una buena idea. El ahorro de memoria rara vez se materializa debido a la alineación de la memoria de los tipos de datos más amplios circundantes. El rendimiento es el mismo o ligeramente peor debido a las instrucciones adicionales necesarias para enmascarar los bytes de relleno.

Como otra respuesta ya lo ha puesto bien, siga la multitud Int32 para la que está optimizado el tiempo de ejecución, hasta que tenga que comenzar a perfilar y direccionar cerdos reales de memoria en su aplicación.

+0

Excelente punto para contrarrestar parte de la desinformación en los otros comentarios. –

Cuestiones relacionadas