Perché le variabili locali devono avere valori iniziali

Perché devo inizializzare le variabili all’interno dei metodi?

int test1; // Not initialized, but ok public int Foo() { int test2; // Not initialized int test3 = test1; // Ok int test4 = test2; // An error } 

I campi vengono automaticamente inizializzati allo zero logico per il tipo; questo è implicito. Le variabili devono obbedire al “compito definito”, quindi devono essere assegnate prima che possano essere lette.

ECMA 334v4

§17.4.4 Inizializzazione del campo

Il valore iniziale di un campo, sia esso un campo statico o un campo istanza, è il valore predefinito (§12.2) del tipo di campo. Non è ansible osservare il valore di un campo prima che si sia verificata questa inizializzazione predefinita, e quindi un campo non è mai “non inizializzato”.

e

§12. variabili

… Una variabile deve essere assegnata definitivamente (§12.3) prima che il suo valore possa essere ottenuto. …

Estendendo la 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 il processo di verifica utilizzando la proprietà SkipVerfication dall’attributo SecurityPermission ), tutte le variabili locali devono essere inizializzate prima del loro utilizzo. In caso contrario, verrà generata una VerficationException .

Più interessante è che il compilatore aggiunge automaticamente il .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. Il significato, anche se li hai già inizializzati nel tuo codice, il JIT si conformsrà al .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 (sostenuta anche 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 nell’ambiente sottostante per inizializzarsi la loro variabile sono valori predefiniti, ma solo perché “dimenticati”, causando quindi errori logici a volte illusori.
Quindi, al fine di ridurre la probabilità che i bug di questa natura appaiano nel codice C #, il compilatore continua a voler inizializzare le variabili locali. Anche se aggiungerà il .locals init al codice IL generato.

Una spiegazione più esauriente su questo argomento può essere trovata qui: Behind The .locals init Flag

In realtà non dovrebbe. Il tuo errore dovrebbe essere sulla seconda riga, non il primo, e dovrebbe essere perché l’hai USATO prima di inizializzarlo.

Il compilatore ti sta aiutando qui.

Quindi non inizializzarli come un’abitudine, invece lascia che il compilatore ti aiuti!

La cosa bella di questo è che controllerà il percorso per te. Se hai un’istruzione switch con 3 casi in cui ognuno imposta il valore ma ti dimentichi di impostarlo nel tuo “predefinito” ma lo usi in seguito ti avviserà che hai perso un percorso.

Se si inizializzano le variabili su = 0, si toglie tale vantaggio.

Come Marc indica, questo è quello che dice la specifica. La ragione per cui questa è una buona cosa è che ci sono alcuni validi motivi per lasciare un membro non inizializzato piuttosto che una variabile locale, la cui durata è limitata dal metodo in cui si trova. Principalmente lo si vorrebbe solo per ragioni di prestazioni, se il la variabile è costosa da inizializzare e deve essere inizializzata solo in specifici scenari di utilizzo. Per parte mia, eviterei i membri non inizializzati fino a che la mia schiena non fosse veramente contro il muro, però!

Per le variabili locali, è anche molto più facile rilevare se tutti i percorsi di codice possono portare all’inizializzazione, mentre non ci sono buone euristiche per determinare se tutti i percorsi di codice nell’intero programma garantiscono l’inizializzazione prima dell’uso. Una risposta completamente corretta è imansible in entrambi i casi , come dovrebbero sapere tutti gli studenti CS.