2012-06-21 5 views
5

No busco mejorar el rendimiento o el uso de la memoria, esta pregunta fue puramente provocada por la curiosidad.¿Cómo se empaquetan los tipos de datos pequeños en C#

pregunta principal Dada la siguiente clase será el compilador de C# (Mono + .NET) empacar las dos variables en short 4 bytes o van a consumir 8 bytes (con la alineación)?

public class SomeClass { 
    short a; 
    short b; 
} 

cuestión secundaria Si la respuesta a la pregunta anterior no era de 4 bytes, lo haría la siguiente oferta alternativa alguna ventaja (donde SomeClass se utiliza en cantidades muy grandes):

// Warning, my bit math might not be entirely accurate! 
public class SomeClass { 
    private int _ab; 

    public short a { 
     get { return _ab & 0x00ff; } 
     set { _ab |= value & 0x00ff; 
    } 
    public short b { 
     get { return _ab >> 8; } 
     set { _ab |= value << 8; } 
    } 
} 
+3

El compilador de C# no tendrá nada que ver con eso, será el tiempo de ejecución. –

+0

Cuando dice "se usa en cantidades muy grandes", ¿a cuántos estamos hablando y cómo se usan? ¿Estás haciendo una matriz/lista/etc. de estos? –

+0

@ReedCopsey Sí, la teoría de este contexto sería una gran lista con acceso frecuente a entradas específicas por índice. –

Respuesta

5

Esto depende del tiempo de ejecución, no el compilador. Puede anular el comportamiento predeterminado con [StructLayout], lo que puede ayudar, aunque el comportamiento predeterminado debería ser correcto.

Dicho esto, si minimizar el tamaño total es un requisito absoluto, es posible que desee considerar un struct en lugar de un class. Al usar una clase, cada instancia de la clase agregará una sobrecarga significativa. Entre la instancia de objeto syncblk, TypeHandle, etc., así como la referencia (que en un sistema de 64 bits es otra de 8 bytes) utiliza una buena cantidad de memoria "extra" por encima y más allá de sus dos cortos. Para más detalles, vea "How the CLR Creates Runtime Objects".

Almacenar sus datos empaquetados en una colección de tipos de valores puede evitar esto por completo, y mantener las instancias a un total de 8 bytes (más la sobrecarga de la colección). Por supuesto, esto cambia la semántica en términos de uso, pero si solo está usando dos cortos, esto reducirá la cantidad de sobrecarga involucrada en su tipo, especialmente en los sistemas de 64 bits.

+0

Gracias chicos, hay algunas respuestas fantásticas aquí. Gracias por el enlace, voy a tener una lectura! –

6

Se depende del tiempo de ejecución, como dice @David_M, pero puede forzarlo utilizando el atributo [StructLayout] que tiene un miembro Pack que puede usar para controlar el embalaje. Alternativamente, puede usar [FieldOffset] para diseñar manualmente los miembros de una estructura (incluso la superposición, que es la forma en que implementa las uniones en .NET).

2

El diseño real depende del tiempo de ejecución, ya que otros lo han comentado principalmente porque podría ejecutar el mismo código en varias plataformas.

Y sí en el caso de muchos objetos que ahorran espacio. Lo que estás buscando es LayoutKind (atributo StructLayout). Te permite empacar miembros a tu gusto. Por ejemplo, con Sequential se asegurará de que esté bien ajustado.

[StructLayout(LayoutKind.Sequential)] 
public class SomeClass { 
    short a; 
    short b; 
} 

Para más información echa un vistazo a MSDN- Structlayout

Cuestiones relacionadas