Perché non vengono automaticamente inizializzate le variabili locali non assegnate?

Sembra che non ci sia modo di avere variabili locali non assegnate nel tuo codice o di controllarle, come sputa il compilatore Use of unassigned local variable dell’errore di Use of unassigned local variable .

Perché il compilatore non utilizza il default(T) su queste variabili in fase di compilazione?

Anche se è più difficile da fare per i tipi di valore, i tipi di riferimento potrebbero essere facilmente inizializzati in null in questo caso, giusto?

Ecco alcuni codici di test:

 public void Test ( ) { int x; string s; if ( x == 5 ) Console.WriteLine ( 5 ); if ( s != null ) Console.WriteLine ( "s" ); } 

che restituisce:

 Use of unassigned local variable 'x' Use of unassigned local variable 's' 

AGGIORNARE:

Per le persone che affermano che ciò non è consentito per una buona ragione, perché è consentito a livello di class?

 public class C { public int X; public string S; public void Print ( ) { Console.WriteLine ( X ); Console.WriteLine ( S ); } } 

Questo codice si compila perfettamente bene.

Perché è bello avere un livello di class ma non a livello di metodo?

Vedo che hai aggiornato la tua domanda, quindi aggiornerò la mia risposta. La tua domanda ha due parti, una relativa alle local variables e l’altra alle instance variables on a class instance . In primo luogo, tuttavia, questa non è realmente una decisione progettuale del compilatore, ma piuttosto una decisione sul design del linguaggio.

Spec Sezione 12.3.1 / 12.3.2

Variabili locali

Sappiamo perché è ansible definire una variabile senza dargli un valore. Una ragione, un esempio di qualcosa di simile:

 int x; // do stuff x = 5; // Wow, I can initialize it later! Console.WriteLine(x); 

Lo standard definisce il motivo per cui questo è un codice valido. Ora, non sono nel team di progettazione C #, ma è logico perché non inizializzeranno automaticamente il codice per te (oltre al colpo di performance quando in realtà non volevi che fosse inizializzato automaticamente).

Di ‘che il codice sopra era la tua intenzione, ma hai dimenticato di inizializzare x = 5; . Se il compilatore avesse automaticamente inizializzato la variabile per te, il codice verrebbe compilato, ma non farebbe nulla di simile.

Certo, questo è un esempio banale, ma questa è stata una decisione progettuale molto buona da parte dei progettisti di linguaggi, poiché avrebbe risparmiato molti mal di testa nel tentativo di capire perché qualcosa non funzionava come previsto.

Come nota a margine, non riesco a pensare a un motivo per cui vorresti definire il codice senza assegnargli qualcosa, o usare il valore predefinito (in ogni caso), per me che probabilmente sarebbe un bug, che io Sono sicuro che ciò che i progettisti del compilatore potrebbero aver determinato.

Variabili di istanza di class

I membri di livello di class sono definiti dallo standard da assegnare inizialmente. In effetti, per essere onesti, le variabili locali al di fuori di quelle dichiarate in una catch , in foreach o in una dichiarazione sono inizialmente non assegnate. Quindi, in realtà, questo è un problema con gli standard, non un problema con il compilatore.

Se dovessi cercare di indovinare perché questo è il caso per quanto riguarda le variabili di istanza delle istanze di class, direi che ha a che fare con il modo in cui la memoria è allocata sull’heap, poiché è lì che le classi sono allocate. Quando una class è allocata nell’heap, tutti i suoi membri devono essere inizializzati e allocati nell’heap con esso. Non è solo ok farlo in un membro della class che una variabile locale, deve essere fatto in questo modo. Semplicemente non possono essere lasciati non assegnati.

C # è un linguaggio “pozzo del successo”.

Questa è una decisione di progettazione, in quanto la lingua è completamente in grado di consentire l’utilizzo di persone che non sono state esplicitamente assegnate. Tuttavia, è normalmente vero che l’utilizzo di tali variabili è errato, che un percorso di codice non ha impostato un valore per qualche motivo. Per evitare tali errori, il compilatore richiede che tutti i locali vengano assegnati prima di essere utilizzati.

1 Perché il compilatore non consente l’uso di variabili non inizializzate?

Perché impedire ciò promuove una buona programmazione.

2 Perché il compilatore consente l’uso di membri di class non inizializzati?

Perché non è ansible tracciarlo con precisione.

Prendendo in considerazione il tuo suggerimento di inizializzare i tipi di riferimento su null, invece del comportamento corrente (il codice buggy causa un errore di compilazione), riceverai invece un errore di runtime durante la dereferenziazione di una variabile non inizializzata. E ‘davvero quello che vuoi?

Considera il seguente codice:

 void blah(IDictionary dict) { for (int i=0; i<10; i++) { if ((i & 11) != 0) { int j; dict.TryGetValue(i, out j); System.Diagnostics.Debug.Print("{0}",j); j++; } } } 

Supponiamo che il metodo TryGetValue dell'implementazione passata di IDictionary non scriva mai effettivamente in j [non ansible se è scritto in C #, ma è ansible se è scritto in un'altra lingua]. Cosa dovrebbe aspettarsi che il codice stampi?

Nulla di ciò nello standard C # richiede che j venga mantenuto quando il codice lascia l'istruzione if , ma nulla richiede che sia resettato a zero tra le iterazioni del ciclo. Mandare una delle due linee di condotta imporrebbe costi aggiuntivi in ​​alcuni casi. Piuttosto che fare entrambi, lo standard consente semplicemente che quando TryGetValue viene chiamato, j possa arbitrariamente mantenere zero o l'ultimo valore che ha mantenuto quando era in ambito. Un simile approccio evita costi inutili, ma sarebbe scomodo se il codice fosse autorizzato a vedere il valore di j tra il momento in cui rientra nell'oscilloscopio e il tempo in cui è scritto (il fatto che il passaggio di una variabile non inizializzata come parametro out per codificare scritto in un'altra lingua esporrà il suo valore era probabilmente non intenzionale).

Perché cosa vuoi lì dentro? vuoi che x sia zero di default e voglio che sia 5 …

se assegnano 0 a int (s) e tutto il mondo inizia assumendo così, allora a un certo punto cambieranno a -1 e questo interromperà così tante applicazioni in tutto il mondo.

in VB6 le variabili erano assegnate a qualcosa di default, credo, e non era buono come sembrava.

quando usi C # o C ++, assegni il valore con quello che vuoi, non con il compilatore.