2013-03-21 16 views
12

Ho un array di byte lungo che devo dichiarare nel mio codice C#. Faccio qualcosa di simile a questo:Dichiarazione di un array di byte costante lungo

public static class Definitions 
{ 
    public const byte[] gLongByteArray = new byte[] { 
     1, 2, 3, 
     //and so on 
    }; 
} 

Ma ottengo un errore che l'array const può essere inizializzato solo con valori null.

Se cambio const in static viene compilato, ma la domanda che ho è questa: quando la dichiaro come public static byte[] gLongByteArray non verrà inizializzata ogni volta che la mia app viene caricata, giusto? In tal caso, la variabile gLongByteArray punta semplicemente a un array definito nel file exe/dll compilato che viene caricato in memoria. La ragione che sto chiedendo è perché questo array è piuttosto lungo e non voglio che il mio programma sprechi i cicli della CPU caricandolo ogni volta che l'app inizia, o peggio, questa classe è referenziata ...

+0

Le implicazioni sulle prestazioni sono minime, anche se è possibile farlo. Il problema più grande è che un 'byte []' non è un ottimo candidato per essere una costante. Si consiglia di utilizzare le costanti per cose che non dovrebbero mai cambiare, ma una sequenza di byte (in particolare una lunga sequenza di byte) potrebbe cambiare in un'implementazione futura. L'uso di "const" fa sì che il compilatore "bake-in" tutti i riferimenti alla costante, il che significa che il valore costante è _duplicato_ in tutto il codice. Se in seguito cambi la costante, solo i moduli compilati rispetto alla nuova costante avranno il nuovo valore. –

+1

Come altri hanno già detto, non prendere decisioni sulle prestazioni sulla base di ipotesi; renderli in base ai fatti. Crea una matrice di dimensioni realistiche e * misura le tue prestazioni di avvio * con e senza di essa. Allora saprai se ha un effetto o meno. Gli array di byte grandi inizializzati dalle costanti vengono gestiti in modo ragionevolmente efficiente. –

+0

@EricLippert: non ci sono indovinelli coinvolti - mai sentito parlare di un debugger? – ahmd0

risposta

26

Costanti tempo di compilazione (quelle dichiarate con la parola chiave const) sono severamente limitate. Nessun codice deve essere eseguito per ottenere una costante di questo tipo, altrimenti non potrebbe essere una costante in fase di compilazione. Le costanti const sono static per impostazione predefinita.

Se si desidera creare una costante e non è possibile utilizzare una costante fase di compilazione, è possibile utilizzare static readonly invece:

public static readonly byte[] longByteArray = new byte[] { 1, 2, 3, 4, 5 }; 

Il static parola chiave assicura viene inizializzato solo una volta, e parte del tipo di dichiarazione (e non ogni istanza). La parola chiave readonly assicura che la variabile longByteArray non possa essere modificata in seguito.

Definitions.longByteArray = new byte[] { 4, 5, 6 }; // Not possible. 

Warning: Un array è mutevole, così nel codice precedente che posso ancora fare questo:

Definitions.longByteArray[3] = 82;     // Allowed. 

Per evitare che, rendere il tipo non un array ma una sola lettura solo interfaccia di raccolta, come ad esempio IEnumerable<T> o IReadOnlyList<T> o, ancora meglio, un tipo di raccolta di sola lettura come ReadOnlyCollection<T> che non consente nemmeno la modifica tramite la trasmissione.

public static readonly IReadOnlyList<byte> longByteArray = new byte[] { 1, 2, 3, 4, 5 }; 
+0

Risposta fine, ma il campione non verrà compilato come 'byte a = 82974;' è un errore in fase di compilazione. –

+0

@AlexeiLevenkov Buona cattura. Ho appena dovuto inventare delle cifre casuali. : P – Virtlink

+0

Nell'ultimo esempio con IReadOnlyLIst, si può ancora lanciarlo su un byte [] e modificare i valori nella matrice. Come puoi vedere [qui] (https://gist.github.com/jcmcbeth/00aee115b6ec18de617729e4e40af655). Se quello era un elenco, puoi utilizzare AsReadonly() alla fine. – jcmcbeth

3

Puoi creare una matrice const. Secondo il documentation:

tipi definiti dall'utente, comprese le classi, le strutture e gli array, non può essere const.

Avresti di dichiararla come un campo di sola lettura statico come questo

public static class Definitions 
{ 
    public static readonly byte[] gLongByteArray = new byte[] { 
     1, 2, 3, 
     //and so on 
    }; 
} 

Naturalmente, non c'è niente da impedire a qualcuno di overwritting tuoi elementi della matrice in fase di esecuzione, in questo modo:

Definitions.gLongByteArray[0] = 0xFF; 

Dovreste usare uno del costruito in collezioni che @Virtlink suggerisce o creare il proprio classe personalizzata gamma di sola lettura per evitare che (example).

0

le classi statiche verranno inizializzate quando si carica l'applicazione per la prima volta. Non preoccuparti delle prestazioni, a meno che tu non abbia specificamente misurato che si tratta di un problema.

+3

Tecnicamente, l'inizializzazione statica avviene in un tempo variabile, a seconda di come/quando viene fatto riferimento alla classe. Questo è raramente un problema, ma vale la pena saperlo. È garantito che sia stato eseguito almeno quando si fa riferimento al campo. –

0

Scrivi tutto il contenuto in un file e incorpora come risorsa!