Estensione della risposta di Mark, l'inizializzazione della variabile locale è anche correlata al processo di verifica .
La CLI richiede che in qualsiasi codice verificabile (ovvero moduli che non hanno chiesto esplicitamente di saltare la procedura di verifica utilizzando la proprietà SkipVerfication dell'attributo SecurityPermission), tutte le variabili locali devono essere inizializzate prima del loro utilizzo. In caso contrario, verrà generato un valore pari a VerficationException.
Più interessante è che il compilatore aggiunge automaticamente il flag .locals init
su ogni metodo che utilizza variabili locali. Questo flag fa in modo che il compilatore JIT generi codice che inizializza tutte le variabili locali ai loro valori predefiniti. Significa che, anche se li hai già inizializzati nel tuo codice, il JIT si conformerà al flag .locals init
e genererà il codice di inizializzazione corretto. Questa "inizializzazione duplicata" non influisce sulle prestazioni poiché nelle configurazioni che consentono ottimizzazioni, il compilatore JIT rileverà la duplicazione e la tratterà efficacemente come "codice morto" (la routine di inizializzazione generata automaticamente non verrà visualizzata nelle istruzioni assembler generate).
Secondo Microsoft (anche, sostenuto da Eric Lippert in risposta a una domanda sul suo blog), nella maggior parte dei casi, quando i programmatori non inizializzano la loro variabile locale, non lo fanno perché si inoltrano sul l'ambiente sottostante per inizializzare la loro variabile sono valori predefiniti, ma solo perché "dimenticati", causando così dei bug logici a volte illusivi.
Quindi, al fine di ridurre la probabilità che i bug di questa natura appaiano nel codice C#, il compilatore insiste ancora che si inizializzeranno le variabili locali. Anche se aggiungerà il flag .locals init
al codice IL generato.
Una spiegazione più esauriente su questo argomento si possono trovare qui: Behind The .locals init Flag
questo è solo ripetere la domanda. Ma perché? –
@YairHalberstadt che dipende da "perché?" uno significa la regola o la ragione dietro la regola. Ho risposto al primo, che probabilmente risponde alla domanda; per il secondo: perché quando hai considerato il concatenamento del costruttore, i metodi virtuali chiamati durante la costruzione e il fatto che i costruttori di base a livello IL possano essere chiamati in qualsiasi punto della catena di chiamate, diventa quasi impossibile dire qualcosa ragionevole sull'inizializzazione del campo; allo stesso modo, i campi possono essere sovrapposti rendendo ancora più importante azzerare lo spazio, quindi non è tecnicamente necessario alcun init - contrasto ... –
@YairHalberstadt variabili locali, che hanno un controllo di assegnazione molto semplice, dove uninitialized di solito significa un errore, e dove può saltare l'azzeramento (anche se il runtime corrente non lo fa mai, IIRC). –