2010-01-06 20 views
6

Controllare questo codice ..Perché i tipi di riferimento non sono inizializzati su null?

string str; 

    if (str.Contains("something..")) 
    { 
    } 

compilatore genera questo errore per questo codice

L'uso della variabile non assegnata 'str' locale

Perché un tipo di riferimento non è inizializzata a null?

Voglio solo sapere per curiosità.

Vorrei anche sapere cosa succede per il codice qui sotto. come funziona questo incarico?

string str = null; 

risposta

20

Solo campi (variabili dichiarate a livello di classe) vengono inizializzati automaticamente:

  • tipi di valore sono inizializzati al loro valore di default.
  • I tipi di riferimento sono inizializzati nel riferimento null.

Quello che stai dichiarando è una "variabile locale" all'interno di un metodo. Le variabili locali non vengono inizializzate automaticamente indipendentemente dal tipo di valore o tipo di riferimento.

Vorrei anche sapere cosa succede per il codice qui sotto. come funziona questo incarico?

Questa assegnazione inizializza la variabile locale con valore nullo con un'istruzione ldnull seguito da un'istruzione stloc (in caso di non ottimizzato fuori, ovviamente) e, soprattutto, soddisfa regole di analisi del flusso di dati del compilatore per l'assegnazione definitiva. La specifica C# definisce un concetto chiamato assegnazione definita che assicura che una variabile venga assegnata prima del primo utilizzo.

+0

Stai parlando di campi che sono tipi di riferimento e ancora inizializzati come null? Allora perché una tale differenza? –

+0

Differenza tra cosa? Essere locali o no? –

+2

@Mehrdad: Penso che voglia sapere perché le variabili locali non sono automaticamente inizializzate al loro valore predefinito in contrapposizione ai campi. Il motivo è perché questo è già un'ottimizzazione. Il compilatore può tranquillamente dire se a una variabile locale è stato assegnato o meno un valore. Se non lo è, il compilatore genererà un errore in fase di compilazione. Questa ottimizzazione non sarebbe possibile per i campi. –

-1

Ricordare inoltre che il richiamo di Contains su una stringa null genererà un'eccezione NullReferenceException.

+0

non verrà compilato affatto. –

+0

Credo di non aver capito. Ho pensato che stavi anche chiedendo cosa succederebbe se avessi il codice che imposta la variabile str su null. In tal caso si verificherà l'eccezione. –

2

viene inizializzato su null. Il compilatore ti ha appena fatto un favore non dovendo eseguire il debug dell'inevitabile NullReferenceException che otterrai.

+0

Mehrdad ha ragione, le variabili locali non vengono effettivamente inizializzate, in quanto sarebbe inutile dato che non è possibile utilizzare una variabile locale finché non viene assegnato un valore, il compilatore non ti lascerà :-) –

+0

Hmya, chicked-and- problema delle uova È consentito in VB.NET, non genera alcun IL per inizializzare la variabile locale. L'inizializzazione viene eseguita dal compilatore JIT. –

+0

Quando si modifica l'esempio precedente per controllare solo la stringa per null, non è ancora possibile compilare poiché le vars non inizializzate non possono nemmeno essere confrontate con null. A volte mi infastidisce quando si passa da C# a java. – FrankKrumnow

6

Il linguaggio C# richiede che tutte le variabili vengano assegnate definitivamente prima della lettura. Le variabili locali sono considerate inizialmente non assegnate, mentre i campi, gli elementi di matrice e così via sono considerati come inizialmente assegnati al loro valore predefinito. (Che, per un tipo di riferimento, è nullo.)

Non vi è alcun motivo tecnico per cui non è stato possibile trattare le variabili locali inizialmente assegnate ai valori predefiniti e eliminare tutti i controlli di assegnazione definiti. È lì perché usare un locale non assegnato come valore predefinito è (1) una cattiva pratica di codifica, e (2) una fonte altamente probabile di bug irritanti.Chiedendo all'utente di assegnare in modo esplicito variabili locali prima che vengano utilizzate, impediamo all'utente di utilizzare una cattiva pratica ed elimina un'intera classe di bug che non è quindi necessario eseguire il debug.

Inoltre, considerare quanto segue:

while(whatever) 
{ 
    int i; 
    print(i); 
    i = i + 1; 
} 

Ti aspetti che a tenere il suo valore attraverso esecuzioni del ciclo, o per essere inizializzato fresco a zero ogni volta? Costringendoti a inizializzarlo esplicitamente, la domanda diventa priva di significato e questa è una differenza che non fa differenza.

(Inoltre, nel caso sopra c'è un piccolo potenziale di ottimizzazione delle prestazioni, in quanto il compilatore può riutilizzare la variabile senza dover generare codice per cancellare il suo contenuto perché il compilatore sa che si si cancellerà il contenuto .)

Non so come rispondere alla seconda domanda perché non so cosa intendi per "lavoro". Puoi dirmi come assegnare "int x = 123;" lavori? Una volta che so cosa intendi per "funziona", allora posso descrivere come funziona l'assegnazione di un valore nullo a una variabile di tipo di riferimento.

+0

Vale la pena notare che se si cambiava la linea 'print' in' OutsideObject.Print (out i); ', chiamando una routine scritta in un'altra lingua, il compilatore generava automaticamente una chiamata per assicurarsi che' i' fosse inizializzato prima della prima chiamata, ma può essere o non essere inizializzata prima delle chiamate successive. Infatti, se 'zz' è un tipo di struttura il cui costruttore passa' questo' come parametro 'out' al codice esterno, anche un'istruzione come' var foo = new zz (2); 'potrebbe non lasciare' foo' completamente intatto. – supercat

Problemi correlati