Domanda

Per qualche ragione, ho sempre pensato che readonly campi di overhead associato con loro, e ho pensato che come il CLR tenere traccia di se o non un readonly il campo è stato inizializzato o non.L'overhead sarebbe qualche extra in memoria di utilizzo per tenere traccia dello stato e un check-in caso di assegnazione di un valore.

Forse ho assunto questo perché non sapevo readonly campo potrebbe essere inizializzato solo all'interno di un costruttore o all'interno del campo di dichiarazione stessa e senza un controllo fase di esecuzione, che non sarebbe in grado di garantire non viene assegnato a più volte in vari metodi.Ma ora so che questo potrebbe facilmente essere staticamente controllato dal compilatore C#, giusto?Quindi è questo il caso?

Un altro motivo è che ho letto che l'uso di readonly ha una 'leggera' impatto sulle prestazioni, ma non è mai entrato in questa domanda e non riesco a trovare informazioni su questo argomento, da qui la mia domanda.Non so cosa altro impatto sulle prestazioni ci potrebbe essere a parte di run-time di controlli.

Un terzo motivo è che ho visto che readonly è conservato nella compilato IL come initonly, così che cosa è la ragione per questo tipo di informazioni per essere il se readonly non è nulla più di una garanzia da parte del compilatore C# che il campo non sia mai ricevuto al di fuori di un costruttore o una dichiarazione?

D'altra parte, ho scoperto che si può impostare il valore di un readonly int attraverso la riflessione senza CLR la generazione di un'eccezione, che non dovrebbe essere possibile se readonly era un tempo di controllo.

Quindi la mia ipotesi è:il 'readonlyness' è solo una fase di compilazione funzione, qualcuno può confermare/negare questo?E se si, qual è il motivo per questo tipo di informazioni per essere inclusi in IL?

È stato utile?

Soluzione

Devi guardare lo stesso punto di vista, come i modificatori di accesso.I modificatori di accesso esiste in IL, ma sono davvero un tempo di controllo?(1) non riesco ad assegnare direttamente i campi private a tempo di compilazione), (2) posso assegnare loro utilizzo di riflessione.Finora sembra che di esecuzione, il controllo del tempo, come readonly.

Ma esaminiamo i modificatori di accesso.Effettuare le seguenti operazioni:

  1. Creare Assemblea A.dll con public class C
  2. Creare un Assembly B.exe che riferimenti A.dll.B.exe utilizza la classe C.
  3. Costruire i due gruppi.In esecuzione B.exe funziona bene.
  4. Ricostruire A.dll ma il set di classe C per interno.Sostituire A.dll in B.exe's directory.

Ora, l'esecuzione di B.exe lancia un'eccezione di runtime.

I modificatori di accesso esiste IL bene, giusto?Così che cosa è il loro scopo?Lo scopo è che gli altri assembly che fanno riferimento a una .Net assembly bisogno di sapere ciò che gli è consentito l'accesso e la cosa non gli è consentito l'accesso, sia in fase di compilazione E di esecuzione.

Readonly sembra avere uno scopo simile, in IL.Si racconta altre assemblee se sono in grado di scrivere in un campo di un particolare tipo.Tuttavia, readonly non sembra per avere la stessa run-time di controllare che i modificatori di accesso esporre nel mio esempio di cui sopra.Sembra che readonly un check a tempo di compilazione e non si verifica in fase di esecuzione.Date un'occhiata a un campione di prestazioni qui: Di sola lettura performance vs const.

Di nuovo, questo non significa che IL è inutile.Il fa in modo che un errore in fase di compilazione si verifica, in primo luogo.Ricordate, quando si crea non si può costruire contro il codice, ma le assemblee.

Altri suggerimenti

Se si utilizza uno standard, variabile di istanza, in sola lettura si esibiranno quasi identico ad una normale variabile. La IL aggiunto diventa un controllo di tempo di compilazione, ma è praticamente ignorato in fase di esecuzione.

Se stai usando un membro statico di sola lettura, le cose sono un po 'diverso ...

Poiché l'elemento statico di sola lettura viene impostato durante il costruttore statico, JIT "sa" che esiste un valore. Non v'è alcuna memoria aggiuntiva -. Sola lettura solo impedisce ad altri metodi di impostazione di questo, ma questo è un controllo di fase di compilazione

Dato che il JIT sa a questo utente non potrà mai cambiare, diventa "hard-coded" in fase di esecuzione, quindi l'effetto finale è proprio come avere un valore const. La differenza è che ci vorrà più tempo durante il tempo di JIT in sé, dal momento che il compilatore JIT ha bisogno di fare lavoro extra per hard-wire il valore della sola lettura in posizione. (Questo sta per essere molto veloce, però.)

Expert C ++ / CLI da Marcus Hegee ha un ragionevolmente buona spiegazione di questo .

Un punto importante non ancora menzionato da qualsiasi altre risposte è che quando un campo di sola lettura si accede, o quando qualsiasi proprietà si accede, la richiesta viene soddisfatta utilizzando una copia dei dati. Se i dati in questione è un tipo di valore con più di 4-8 byte di dati, il costo di questo copia in più a volte può essere significativo. Si noti che, mentre v'è un grande salto in termini di costi, quando le strutture crescono da 16 byte a 17, le strutture possono essere un po 'più grande e di essere ancora più veloce di classi in molte applicazioni, se non sono copiati troppo spesso . Ad esempio, se si suppone di avere un tipo che rappresenta i vertici di un triangolo nello spazio tridimensionale. Un'implementazione semplice sarebbe una struttura che contiene una struttura con tre float per ogni punto; probabilmente 36 byte totali. Se i punti e le coordinate all'interno di ogni punto, sono campi pubblici mutabili, si può accedere someTriangle.P1.X modo semplice e veloce, senza dover copiare i dati tranne la coordinata Y dei vertici 1. D'altra parte, se P1 era una proprietà o un campo readonly, il compilatore avrebbe dovuto copiare P1 ad una struttura temporanea, e poi leggere X da questo.

Anche se sola lettura solo avuto effetto in fase di compilazione, sarebbe comunque necessario memorizzare i dati nel montaggio (cioè la IL). Il CLR è un Comune Lingua Runtime -. Classi scritte in una lingua entrambi possono essere utilizzati ed estesi da altri linguaggi

Dato che ogni compilatore per il CLR non ha intenzione di saper leggere e compilare tutte le altre lingue, al fine di preservare la semantica dei campi readonly, che i dati devono essere memorizzati in assemblea in modo che i compilatori per altri linguaggi saranno rispettarla.

Naturalmente, il fatto che il campo è contrassegnato readonly significa che il JIT può fare altre cose, come l'ottimizzazione (ad esempio uso in linea del valore), ecc A prescindere dal fatto che si è utilizzato riflessione per modificare il valore del campo, la creazione di iL che modifica un campo initonly fuori della corrispondente costruttore (esempio o statico, a seconda del tipo di campo), si tradurrà in un assieme incontrollabile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top