2012-06-21 17 views
5

Non sto cercando di migliorare le prestazioni o l'utilizzo della memoria, questa domanda è stata puramente scatenata dalla curiosità.Come vengono impacchettati i piccoli tipi di dati in C#

principale domanda Data la seguente classe sarà il compilatore C# (Mono + NET) imballare i due short variabili in 4 byte o si consumano 8 byte (con allineamento)?

public class SomeClass { 
    short a; 
    short b; 
} 

questione secondaria Se la risposta alla domanda di cui sopra non è stato di 4 byte, sarebbe la seguente offerta alternativa alcun vantaggio (dove SomeClass viene utilizzato in grandi quantità):

// 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

Il compilatore C# non avrà nulla a che fare con esso - sarà il runtime. –

+0

Quando si dice "viene usato in quantità molto grandi" - di quanti stiamo parlando e in che modo vengono utilizzati? Stai facendo un array/elenco/etc di questi? –

+0

@ReedCopsey Sì, la teoria di questo contesto sarebbe una grande lista con accesso frequente a voci specifiche per indice. –

risposta

5

Questo dipende dal tempo di esecuzione, non il compilatore. È possibile ignorare il comportamento predefinito con [StructLayout], che può essere d'aiuto, anche se il comportamento predefinito dovrebbe andare bene.

Detto questo, se la riduzione delle dimensioni totali è un requisito assoluto, è possibile prendere in considerazione un struct anziché uno class. Quando si utilizza una classe, ogni istanza della classe aggiungerà un sovraccarico significativo. Tra il syncblk, TypeHandle, ecc., Nonché il riferimento (che su un sistema a 64 bit è di altri 8 byte) l'istanza dell'oggetto utilizza una discreta quantità di memoria "extra" al di sopra e al di là dei tuoi due cortocircuiti. Per dettagli, vedere "How the CLR Creates Runtime Objects".

Memorizzare i dati in una raccolta di tipi di valori può evitarlo completamente e mantenere le istanze fino a 8 byte per totale (oltre al sovraccarico della raccolta). Di conseguenza, questo cambia la semantica in termini di utilizzo, ma se stai usando solo due cortocircuiti, questo ridurrà la quantità di costi aggiuntivi coinvolti nel tuo tipo, specialmente sui sistemi a 64 bit.

+0

Grazie ragazzi, ci sono alcune risposte fantastiche qui. Grazie per il link, avrò una lettura! –

6

E ' dipende dal runtime, come dice @David_M, ma puoi forzarlo usando l'attributo [StructLayout] che ha un membro Pack che puoi usare per controllare l'imballaggio. In alternativa è possibile utilizzare [FieldOffset] per disporre manualmente i membri di una struct (anche sovrapporre, ovvero come implementare i sindacati in .NET).

2

Il layout effettivo dipende dal runtime in quanto altri hanno commentato principalmente perché è possibile eseguire lo stesso codice su più piattaforme.

E sì nel caso di molti oggetti che consente di risparmiare spazio. Quello che stai cercando è LayoutKind (attributo StructLayout). Ti consente di impacchettare i membri come preferisci. Ad esempio con Sequential si accerterà che sia pieno zeppo.

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

Per maggiori informazioni Check out MSDN- Structlayout

Problemi correlati