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.
Tip
Avvio di un nuovo progetto? I nuovi progetti creati a partire dai modelli di .NET 6 o versioni successive sono già impostati con <Nullable>enable</Nullable>. Non è necessaria una strategia di migrazione: vai direttamente a Risoluzione degli avvisi relativi ai valori nullable.
Gestione di una codebase esistente? Leggi prima Tipi di riferimento nullable per comprendere contesti, annotazioni e stato null. Questo articolo presuppone che si abbia familiarità con questi concetti e si sia pronti a pianificare un'implementazione.
Quando si attivano i tipi riferimento nullable in un progetto di grandi dimensioni avviato prima dell'introduzione di tipi riferimento nullable, il compilatore genera molti avvisi contemporaneamente. La migrazione consiste nello scandire il lavoro: scegliere un contesto predefinito, mostrare gli avvisi file per file o sezione per sezione e convergere su <Nullable>enable</Nullable> per l'intero progetto. La sequenza corretta dipende dal modo in cui è attiva la codebase e dal rischio che è possibile prendere in un singolo passaggio.
Lo stato finale è lo stesso in ogni caso: il progetto imposta <Nullable>enable</Nullable> e non contiene direttive del preprocessore #nullable.
Scegliere un contesto predefinito
Il contesto con valori Null ha due flag indipendenti: annotazioni (se ? dichiara un tipo riferimento con valori Null) e avvisi (se il compilatore emette diagnosi). Impostali insieme come un unico valore <Nullable>:
| Valore predefinito | Annotations | Avvisi | Ideale per |
|---|---|---|---|
disable
(implicito) |
spento | spento | Le librerie stabili che non richiederanno nuove funzionalità in questo passaggio. |
enable |
su | su | Codebase attive con nuovi file frequenti. Il nuovo codice inizia con l’attivazione. |
warnings |
spento | su | Migrazione in due fasi: risolvere prima gli avvisi, annotare in un secondo momento. |
annotations |
su | spento | Annotare l'API pubblica prima di correggere gli avvisi interni. |
Scegliere la strategia più adatta agli obiettivi per la migrazione del progetto:
- Disabilitare come impostazione predefinita. Impostare
<Nullable>disable</Nullable>e aggiungere#nullable enablenella parte superiore di ogni file durante la migrazione. I file esistenti restano inconsapevoli della nullabilità finché non vengono modificati. Questa opzione comporta le minori difficoltà per le librerie stabili, perché si lavora raramente a nuove funzionalità. - Abilita come impostazione predefinita. Impostare
<Nullable>enable</Nullable>e aggiungere#nullable disablenella parte superiore di ogni file di cui non è ancora stata eseguita la migrazione. Ogni nuovo file è predisposto per la nullabilità fin dall'inizio, quindi il backlog di migrazione può solo ridursi. Questa scelta è migliore quando lo sviluppo è attivo. - Avvisi come impostazione predefinita. Imposta
<Nullable>warnings</Nullable>. Scegli questa impostazione predefinita per una migrazione in due fasi: affronta gli avvisi mentre ogni tipo di riferimento è ancora considerato non specificato, quindi attiva le annotazioni. La suddivisione in due fasi mantiene il diff di ogni passaggio ben focalizzato. - Annotazioni come predefinite. Imposta
<Nullable>annotations</Nullable>. Iniziare annotando l'API pubblica (?sui membri che consentononull) prima di inseguire gli avvisi. Il compilatore non genera ancora avvisi, quindi è possibile risolvere la superficie dell'API senza distrazioni.
Il file di progetto controlla l'impostazione predefinita globale.
#nullableLe direttive del preprocessore eseguono l'override di tale impostazione predefinita per un'area di codice:
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
All'interno dei file di origine, la direttiva opta per un'area all'interno o all'esterno dell'impostazione nullable del progetto:
#nullable disable
public static class LegacyHelper
{
// This file is nullable-oblivious. Reference types use the legacy rules.
public static string GetGreeting(string name) =>
name == null ? "hello" : $"hello {name}";
}
#nullable restore
#nullable enable
public static class MigratedHelper
{
// This file is fully migrated. Reference types are non-nullable by default.
public static string GetGreeting(string? name) =>
name is null ? "hello" : $"hello {name}";
}
#nullable restore
Eseguire la migrazione file per file
Il modo più prevedibile per eseguire la migrazione di un progetto di grandi dimensioni consiste nell'abilitare avvisi o file di annotazioni in base al file. Il modello è lo stesso indipendentemente dal valore predefinito scelto:
- Selezionare un file. Iniziare con i tipi foglia più profondi nel grafico delle dipendenze, quindi procedere verso l'esterno. Annotare un tipo provoca nuovi avvisi nei chiamanti, quindi lavorare dal basso verso l’alto riduce al minimo le rilavorazioni.
- Aggiungi la direttiva
#nullableche fa sì che il file adotti il nuovo comportamento. Usa#nullable enablese vuoi entrambi i flag. Usare#nullable enable warningssolo per gli avvisi. - Gestire gli avvisi nel file utilizzando le tecniche descritte in Risolvere gli avvisi sulla nullabilità.
- Ripetere per il file successivo.
- Quando ogni file nel progetto ha la relativa direttiva, rimuovere le direttive e impostare
<Nullable>enable</Nullable>a livello di progetto.
Se la tua base di codice ha già <Nullable>enable</Nullable>, state andando nella direzione opposta. Nascondi gli avvisi nei file non migrati finché non sei pronto. Usa #nullable disable per escludere i file, quindi rimuovi le soppressioni una alla volta.
Eseguire la migrazione in due fasi
Una migrazione in due fasi separa i due tipi di lavoro che i tipi riferimento nullable comportano. È possibile sequenziare le fasi in entrambi i modi, a seconda della forma di stabilità più importante per te.
Avvisi prima, quindi annotazioni
Il lead con avvisi durante la correzione di bug latenti System.NullReferenceException è la priorità:
- Fase 1: Risolvere gli avvisi. Impostare il progetto predefinito su
warnings. I tipi di riferimento rimangono non sensibili alla nullabilità, quindi il sistema di tipi non cambia ancora. Il compilatore genera avvisi in tutti i punti in cui il codice esistente potrebbe già sollevare un System.NullReferenceException. Aggiungi controlli null, ristruttura il flusso o applica attributi finché il progetto non è privo di avvisi. Ogni correzione rende il codice di produzione più resiliente anche prima che esistano annotazioni. - Fase 2: Aggiungere annotazioni. Impostare come predefinito il progetto su
enable. I tipi di riferimento ora non ammettono valori null per impostazione predefinita, e le variabili localivarpossono assumere valori null. I nuovi avvisi riflettono le dichiarazioni che non corrispondono al modo in cui vengono usate le variabili. Aggiungere?ai tipi che dovrebbero consentirenull. Limitare le API che devono accettare solo input non null.
Annotazioni prima, quindi avvisi
Privilegia le annotazioni quando la priorità è stabilizzare la superficie dell'API pubblica. Questa sequenza è adatta alle librerie: è possibile distribuire firme annotate in modo che gli utenti vedano i contratti corretti, per poi risolvere gli avvisi interni secondo le proprie tempistiche.
- Fase 1: Aggiungere annotazioni. Impostare il progetto predefinito su
annotations. I tipi di riferimento diventano non annullabili per impostazione predefinita, ma il compilatore non emette avvisi, evitando così di intralciarti. Esaminare l'API pubblica e aggiungere?a ogni membro che può restituire o accettarenulllegittimamente . Restringere le firme che non dovrebbero. Poiché gli avvisi sono disattivati, puoi definire la struttura dell'API in commit mirati senza dover dipanare anche l'implementazione allo stesso tempo. - Fase 2: Risolvere gli avvisi. Impostare come predefinito il progetto su
enable. Le annotazioni aggiunte nella fase 1 ora alimentano l’analisi dello stato null, quindi gli avvisi emessi dal compilatore sono di qualità migliore fin dall’inizio: ognuno di essi punta al codice il cui comportamento non corrisponde al contratto che hai già pubblicato. Risolverli usando le tecniche descritte in Risolvere gli avvisi relativi ai valori nullable.
Scelta tra gli ordini
Ogni ordinamento separa le fasi in differenze più piccole e verificabili. Una fase modifica solo il comportamento e gli altri modificano solo i tipi. Lo svantaggio è che si visita ogni file due volte. Per codice maturo e stabile in cui ogni modifica comporta rischi, i due passaggi in genere ne vale la pena. Selezionare gli avvisi per la prima volta quando si vuole rafforzare la protezione avanzata del codice in esecuzione. Selezionare le annotazioni per prime quando si vuole pubblicare un contratto stabile.
Il codice generato viene escluso
Il compilatore considera i file contrassegnati come generati come se il contesto nullable fosse disabilitato, indipendentemente dall'impostazione del progetto. Un file viene considerato generato quando viene soddisfatta una delle condizioni seguenti:
- Una regola
.editorconfigimpostagenerated_code = trueper il file. - Il primo commento nel file contiene
<auto-generated>o<auto-generated/>. - Il nome del file inizia con
TemporaryGeneratedFile_. - Il nome file termina con
.designer.cs,.generated.cs,.g.cso.g.i.cs.
I generatori che producono output compatibile con i tipi nullable possono riattivare questo comportamento emettendo #nullable enable all'inizio del file generato.
Quando hai finito
Dopo che ogni file partecipa all'impostazione predefinita del progetto e l'elemento <Nullable>enable</Nullable> è impostato:
- Rimuovi ogni direttiva
#nullablenel sorgente. - Rimuovi gli inizializzatori
null!edefault!che hai aggiunto solo per eliminare gli avvisi durante la migrazione. Sostituirle con un'inizializzazione appropriata oppure fare in modo che il tipo sia un tipo di riferimento nullable. - Verificare a campione l'API pubblica. Ogni membro che restituisce o accetta
nulldeve essere annotato con?. Le annotazioni fanno parte del contratto una volta che il pacchetto viene fornito.
Ora ti trovi nella stessa condizione dei nuovi progetti: i tipi di riferimento nullable fanno parte del sistema dei tipi e qualsiasi nuovo avviso riflette una reale discrepanza tra dichiarazioni e codice. Usare Risolvi gli avvisi relativi ai valori Null per affrontarli man mano che si presentano.