Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
I tipi di riferimento nullable consentono di dichiarare se alle variabili di un tipo di riferimento deve essere assegnato o meno un null valore. L'analisi statica e gli avvisi del compilatore quando il codice potrebbe dereferenziare il valore null sono il vantaggio più importante di questa funzionalità. Dopo l'abilitazione, il compilatore genera avvisi che consentono di evitare di generare un'eccezione System.NullReferenceException durante l'esecuzione del codice.
Se la codebase è relativamente piccola, è possibile attivare la funzionalità nel progetto, risolvere gli avvisi e sfruttare i vantaggi della diagnostica migliorata. Le codebase più grandi possono richiedere un approccio più strutturato per risolvere gli avvisi nel tempo, abilitando la funzionalità per alcuni di essi man mano che si affrontano avvisi in diversi tipi di file. Questo articolo descrive diverse strategie per aggiornare una codebase e i compromessi associati a queste strategie. Prima di iniziare la migrazione, leggi la panoramica concettuale dei tipi di riferimento nullable. che illustra l'analisi statica del compilatore, i valori di null-statemaybe-null e not-null e le annotazioni nullable. Dopo aver acquisito familiarità con questi concetti e termini, è possibile eseguire la migrazione del codice.
Pianificare la migrazione
Indipendentemente dal modo in cui si aggiorna la codebase, l'obiettivo è che nel progetto siano abilitati avvisi e annotazioni nullable. Dopo aver raggiunto tale obiettivo, nel progetto si avrà l'impostazione <nullable>Enable</nullable>. Non sono necessarie le direttive del preprocessore per regolare le impostazioni altrove.
Nota
È possibile designare un'impostazione Nullable per il progetto usando un tag <Nullable>. Per altre informazioni, vedere Opzioni del compilatore.
La prima scelta consiste nell'impostare il valore predefinito per il progetto. Le opzioni sono:
-
Disabilitare nullable come impostazione predefinita: disable è l'impostazione predefinita se non si aggiunge un elemento
Nullableal file di progetto. Usare questa impostazione predefinita quando non si aggiungono attivamente nuovi file alla codebase. L'attività principale consiste nell'aggiornare la libreria per usare i tipi di riferimento nullable. L'uso di questo valore predefinito significa che l'utente aggiunge una direttiva del preprocessore nullable a ogni file durante l'aggiornamento del codice. -
Abilita nullable come impostazione predefinita: impostalo come valore predefinito quando sviluppi attivamente nuove funzionalità. Si vuole che tutto il nuovo codice tragga vantaggio dai tipi di riferimento nullable e dall'analisi statica dei tipi nullable. L'uso di questo valore predefinito significa che è necessario aggiungere
#nullable disableall'inizio di ogni file. Rimuoverai queste direttive del preprocessore mentre affronti gli avvisi in ogni file. -
Avvisi nullable come impostazione predefinita: si consiglia di scegliere questa impostazione predefinita per una migrazione in due fasi. Nella prima fase, affrontare gli avvisi. Nella seconda fase attivare le annotazioni per dichiarare lo stato null previsto di una variabile. L'uso di questo valore predefinito significa che è necessario aggiungere
#nullable disableall'inizio di ogni file. - Annotazioni di nullabilità come impostazione predefinita. Annotare il codice prima di risolvere gli avvisi.
L'abilitazione di nullable come impostazione predefinita crea più lavoro iniziale per aggiungere le direttive del preprocessore a ogni file. Il vantaggio è che ogni nuovo file di codice aggiunto al progetto sarà abilitato per i valori null. Qualsiasi nuovo lavoro riconoscerà i valori null; è necessario aggiornare solo il codice esistente. La disabilitazione di nullable come impostazione predefinita funziona meglio se la libreria è stabile e l'obiettivo principale dello sviluppo consiste nell'adottare tipi riferimento nullable. Attivi i tipi di riferimento nullable mentre annoti le API. Quando hai finito, abilita i tipi di riferimento nullable per l'intero progetto. Quando si crea un nuovo file, è necessario aggiungere le direttive del preprocessore e renderle in grado di riconoscere i valori null. Se alcuni sviluppatori del team lo dimenticano, il nuovo codice viene ora inserito nel backlog di lavoro per rendere tutto il codice consapevole dei valori null.
Quale di queste strategie si sceglie dipende da quanto sviluppo attivo è in corso nel tuo progetto. Più maturo e stabile è il progetto, migliore sarà la seconda strategia. Più funzionalità vengono sviluppate, migliore sarà la prima strategia.
Importante
Il contesto globale che ammette valori Null non si applica ai file di codice generati. In entrambe le strategie, il contesto nullable è disabilitato per qualsiasi file di origine contrassegnato come generato. Ciò significa che le API nei file generati non vengono annotate. Esistono quattro modi in cui un file viene contrassegnato come generato:
- In .editorconfig specificare
generated_code = truein una sezione che si applica a tale file. - Inserire
<auto-generated>o<auto-generated/>in un commento all'inizio del file. Può trovarsi in qualsiasi riga di tale commento, ma il blocco di commento deve essere il primo elemento del file. - Iniziare il nome del file con TemporaryGeneratedFile_
- Terminare il nome del file con .designer.cs, .generated.cs, .g.cs o .g.i.cs.
I generatori possono acconsentire esplicitamente usando la direttiva del preprocessore #nullable.
Comprendere contesti e avvisi
L'abilitazione di avvisi e annotazioni controlla il modo in cui il compilatore visualizza i tipi di riferimento e la nullabilità. Ogni tipo ha una delle tre nullabilità:
- oblivious: tutti i tipi di riferimento sono oblivious nullable quando il contesto di annotazione è disabilitato.
-
nonnullable: un tipo riferimento senza annotazioni,
C, è nonnullable quando il contesto di annotazione è abilitato. -
nullable: un tipo riferimento con annotazioni,
C?, è nullable, ma può essere generato un avviso quando il contesto di annotazione è disabilitato. Le variabili dichiarate convarsono nullable quando il contesto di annotazione è abilitato.
Il compilatore genera avvisi in base a quella nullabilità.
- I tipi nonnullable generano avvisi se viene assegnato loro un valore potenziale
null. - I tipi nullable generano avvisi se dereferenziati quando è presente un valore maybe-null.
- I tipi oblivious generano avvisi se vengono dereferenziati quando è presente un valore maybe-null e il contesto di avviso è abilitato.
Ogni variabile ha uno stato nullable predefinito che dipende dalla sua nullabilità.
- Le variabili nullable hanno un null-state predefinito di maybe-null.
- Le variabili non-nullable hanno uno stato predefinito di null-statenot-null.
- Le variabili nullable non-ignoranti hanno uno stato predefinito not-null dello stato di nullità.
Prima di abilitare i tipi riferimento nullable, tutte le dichiarazioni nella codebase sono nullable oblivious. Questo è importante perché significa che tutti i tipi di riferimento hanno uno stato predefinito null di non nullo.
Affrontare gli avvisi
Se il tuo progetto utilizza Entity Framework Core, dovresti leggere le loro indicazioni su Lavorare con tipi di riferimento nullable.
Quando si avvia la migrazione, è consigliabile iniziare abilitando solo gli avvisi. Tutte le dichiarazioni rimangono nullable oblivious, ma vengono visualizzati avvisi se si dereferenzia un valore quando lo statonull-state diventa maybe-null. Affrontando questi avvisi, si effettueranno controlli contro null in più posizioni, rendendo la codebase più resiliente. Per informazioni sulle tecniche specifiche per situazioni diverse, vedere l'articolo sulle tecniche per risolvere gli avvisi nullable.
È possibile risolvere gli avvisi e abilitare le annotazioni in ogni file o classe prima di continuare con un altro codice. Tuttavia, è spesso più efficiente risolvere gli avvisi generati mentre il contesto è warnings prima di abilitare le annotazioni del tipo. In questo modo, tutti i tipi sono inconsapevoli fino a quando non hai risolto il primo insieme di avvisi.
Abilitare annotazioni di tipo
Dopo aver risolto il primo set di avvisi, è possibile abilitare il contesto di annotazione. Questo cambia i tipi riferimento da oblivious a nonnullable. Tutte le variabili dichiarate con var sono nullable. Questa modifica introduce spesso nuovi avvisi. Il primo passaggio nel risolvere gli avvisi del compilatore consiste nell'usare annotazioni ? sui parametri e sui tipi restituiti per indicare quando gli argomenti o i valori restituiti possono essere null. Quando si esegue questa attività, l'obiettivo non è solo correggere gli avvisi. L'obiettivo più importante è quello di far comprendere al compilatore la finalità per i potenziali valori Null.
Gli attributi estendono le annotazioni del tipo
Sono stati aggiunti diversi attributi per esprimere informazioni aggiuntive sullo stato Null delle variabili. Le regole per le API sono probabilmente più complesse di not-null o maybe-null per tutti i parametri e i valori restituiti. Molte API hanno regole più complesse per i casi in cui le variabili possono o meno essere null. In questi casi si useranno gli attributi per esprimere tali regole. Gli attributi che descrivono la semantica dell'API sono disponibili nell'articolo sugli attributi che influiscono sull'analisi nullable.
Passaggi successivi
Dopo aver risolto tutti gli avvisi successivamente all'abilitazione delle annotazioni, è possibile impostare il contesto predefinito per il progetto su abilitato. Se hai aggiunto pragma nel tuo codice per l'annotazione nullable o il contesto di avviso, puoi rimuoverli. Nel tempo, potrebbero essere visualizzati nuovi avvisi. È possibile scrivere il codice che introduce gli avvisi. Una dipendenza della libreria può essere aggiornata per i tipi di riferimento nullabile. Tali aggiornamenti modificheranno i tipi di tale libreria da nullable oblivious a nonnullable o nullable.
È anche possibile esplorare questi concetti nel modulo Learn sulla sicurezza dei valori Null in C#.