Avviso di riferimento null di Visual Studio: perché nessun errore?
-
06-07-2019 - |
Domanda
Ho notato qualcosa di strano in Visual Studio. Innanzitutto, prova a digitare questo (C #) da qualche parte in una funzione:
class Foo
{
public void Bar()
{
string s;
int i = s.Length;
}
}
Ora, subito contrassegna s
in s.Length
come errore, dicendo " Uso di variabili locali non assegnate 's'
" ;. D'altra parte, prova questo codice:
class Foo
{
private string s;
public void Bar()
{
int i = s.Length;
}
}
Compilerà e sottolineerà s
in stringa privata s
con un avvertimento, dicendo " Il campo 'Foo.s' non è mai assegnato a, e avrà sempre il valore predefinito null
" ;.
Ora, se VS è così intelligente e sa che s sarà sempre nullo, perché non è un errore ottenere la sua lunghezza nel secondo esempio? La mia ipotesi originale era, " Dà un errore di compilazione solo se il compilatore semplicemente non può completare il suo lavoro. Poiché il codice viene eseguito tecnicamente finché non si chiama mai Bar (), è solo un avvertimento. & Quot; Tranne che la spiegazione è invalidata dal primo esempio. Puoi comunque eseguire il codice senza errori purché non chiami mai Bar (). Quindi cosa dà? Solo una svista o mi sto perdendo qualcosa?
Soluzione
Il primo esempio (l'errore) è un esempio di rilevamento dell'assegnazione definita e che viene applicato solo alle variabili locali. A causa del contesto limitato, il compilatore ha una stretta ermetica su questa situazione. Nota che s
non è nullo, non è definito.
Nel secondo esempio, s
è un campo (e il valore predefinito è null). Non si verifica alcun errore del compilatore, ma verrà sempre rilevato in fase di esecuzione. Questo caso particolare potrebbe essere intrappolato ma questo tipo di errore non è generalmente rilevabile dal compilatore.
Ad esempio, potresti aggiungere un metodo Bar2 ()
che assegna una stringa a s
ma chiamarla più tardi di Bar ()
, oppure non in tutti. Ciò eliminerebbe l'avviso ma non l'errore di runtime.
Quindi è di progettazione.
Altri suggerimenti
Per il secondo esempio il codice è valido, potrebbe non funzionare correttamente. Ecco alcuni casi in cui questo programma potrebbe eseguire "correttamente"
- Il compilatore non è corretto al 100%. È possibile per " s " avere un valore non nullo se un'istanza viene modificata tramite reflection.
- Il programma può essere eseguito senza errori se il metodo Bar non viene mai chiamato
- Questo programma potrebbe essere un programma di test che sta attivando un'eccezione NullReferenceException per motivi di test
L'unica ipotesi che posso fare è che nel secondo esempio, s potrebbe essere modificato tramite reflection (usando BindingFlags.Private per accedere al membro privato).
Nel primo esempio s è una variabile locale e il compilatore può facilmente verificare che la variabile s non sia stata assegnata prima di essere utilizzata.
Nella seconda, s è una variabile globale ed è possibile che sia stata inizializzata da qualche altra parte in una classe.