Condividi tramite


Risolvere gli avvisi nullabili

Lo scopo degli avvisi di nullabilità è ridurre al minimo la probabilità che l'applicazione generi un'eccezione System.NullReferenceException durante l'esecuzione. Per raggiungere questo obiettivo, il compilatore usa l'analisi statica e genera avvisi quando il codice include costrutti che potrebbero causare eccezioni di riferimento Null. È possibile fornire al compilatore informazioni per l'analisi statica applicando annotazioni e attributi di tipo. Queste annotazioni e attributi descrivono la nullabilità di argomenti, parametri e membri dei tuoi tipi. In questo articolo vengono illustrate diverse tecniche per risolvere gli avvisi nullable generati dal compilatore dall'analisi statica. Le tecniche descritte di seguito sono per il codice C# generale. Impara a lavorare con i tipi riferimento nullable e Entity Framework Core in Lavorare con i tipi riferimento nullable.

I tipi di riferimento nullable, inclusi gli operatori ? e !, sono consentiti solo quando il contesto nullable è impostato su enable o annotations. È possibile impostare il contesto nullable usando l'opzione del compilatore Nullable nel file di progetto oppure usando il pragma #nullable nel codice sorgente.

Questo articolo illustra gli avvisi del compilatore seguenti:

  • CS8597 - Il valore generato può essere Null.
  • CS8598 - L'operatore di eliminazione non è consentito in questo contesto
  • CS8600 - Conversione di un valore letterale null o di un valore potenzialmente null in un tipo che non ammette i valori null.
  • CS8601 - Possibile assegnazione di riferimento Null.
  • CS8602 - Dereferenziamento di un riferimento possibilmente null.
  • CS8603 - Possibile ritorno di un riferimento nullo.
  • CS8604 - Argomento di riferimento Null possibile per il parametro.
  • CS8605 - Unboxing di un valore che potrebbe essere nullo.
  • CS8607 - Un possibile valore Null non può essere usato per un tipo contrassegnato con [NotNull] o [DisallowNull]
  • CS8608 - Il supporto dei tipi di riferimento nel tipo non corrisponde al membro sovrascritto.
  • CS8609 - La nullabilità dei tipi riferimento nel tipo restituito non corrisponde al membro sovrascritto.
  • CS8610 - La nullabilità dei tipi di riferimento nel parametro di tipo non coincide con il membro sovrascritto.
  • CS8611 - La nullabilità dei tipi di riferimento nel parametro di tipo non corrisponde alla dichiarazione del metodo parziale.
  • CS8612 - La nullabilità dei tipi di riferimento nel tipo non corrisponde al membro implementato implicitamente.
  • CS8613 - La nullabilità dei tipi riferimento nel tipo di ritorno non corrisponde al membro implementato implicitamente.
  • CS8614 - La nullabilità dei tipi di riferimento nel tipo del parametro non corrisponde al membro implementato implicitamente.
  • CS8615 - La nullabilità dei tipi di riferimento nel tipo non corrisponde a quella del membro implementato.
  • CS8616 - La nullabilità dei tipi di riferimento nel tipo di restituzione non corrisponde al membro implementato.
  • CS8617 - La nullabilità dei tipi di riferimento nel tipo di parametro non corrisponde al membro implementato.
  • CS8618 - La variabile non nullable deve contenere un valore non null quando si esce dal costruttore. Valutare la possibilità di dichiararla come nullable.
  • CS8619 - La nullabilità dei tipi di riferimento nel valore non corrisponde al tipo target.
  • CS8620 - L'argomento non può essere usato per il parametro a causa delle differenze nella nullabilità dei tipi di riferimento.
  • CS8621 - La nullabilità dei tipi di riferimento nel tipo di ritorno non corrisponde al delegato di destinazione (probabilmente a causa degli attributi di nullabilità).
  • CS8622 - La nullabilità dei tipi riferimento nel tipo di parametro non corrisponde al delegato di destinazione (probabilmente a causa di attributi di nullabilità).
  • l'applicazione esplicita di System.Runtime.CompilerServices.NullableAttribute non è consentita - CS8623.
  • CS8624 - L'argomento non può essere usato come output a causa di differenze nella nullabilità dei tipi di riferimento.
  • CS8625 - Non è possibile convertire un valore letterale Null in un tipo riferimento che non ammette i valori Null.
  • - CS8628 Non è possibile utilizzare un tipo di riferimento nullable nella creazione dell'oggetto.
  • CS8629 - Un tipo di valore nullable può essere null.
  • CS8631 - Il tipo non può essere utilizzato come parametro di tipo nel tipo o nel metodo generico. La nullabilità dell'argomento di tipo non corrisponde al tipo di vincolo.
  • CS8632 - Le annotazioni sui tipi di riferimento nullable devono essere utilizzate solo nel codice all'interno di un contesto di annotazioni #nullable.
  • CS8633 - La nullabilità nei vincoli per il parametro di tipo del metodo non corrisponde ai vincoli per il parametro di tipo del metodo dell'interfaccia. Considera di utilizzare un'implementazione esplicita dell'interfaccia.
  • CS8634 - Il tipo non può essere utilizzato come argomento di tipo nel tipo o nel metodo generico. La nullabilità dell'argomento di tipo non corrisponde al vincolo 'class'.
  • CS8636 - opzione Non valida per /nullable; deve essere disable, enable, warnings o annotations
  • CS8637 - Previsto enable, disableo restore
  • CS8639 - L'operatore typeof non può essere usato su un tipo di riferimento nullable
  • CS8643 - La nullabilità dei tipi riferimento nello specificatore di interfaccia esplicito non corrisponde all'interfaccia implementata dal tipo.
  • CS8644 - Il tipo non implementa il membro dell'interfaccia. La nullabilità dei tipi riferimento nell'interfaccia implementata dal tipo base non corrisponde.
  • CS8645 - Il membro è già elencato nella lista delle interfacce su un tipo con diversa annullabilità dei tipi di riferimento.
  • CS8655 - L'espressione switch non gestisce alcuni input Null (non è esaustivo).
  • CS8667 - Le dichiarazioni di metodi parziali hanno una nullabilità incoerente nei vincoli per il parametro di tipo.
  • CS8670 - L'inizializzatore di oggetti o collezioni dereferenzia implicitamente un membro eventualmente null.
  • CS8714 - Il tipo non può essere utilizzato come parametro di tipo nel tipo generico o nel metodo. La gestibilità di valori nulli dell'argomento di tipo non corrisponde al vincolo 'notnull'.
  • CS8762 - Il parametro deve avere un valore non Null quando si esce.
  • CS8763 - Un metodo contrassegnato [DoesNotReturn] non deve restituire.
  • CS8764 - La nullabilità del tipo restituito non corrisponde al membro sottoposto a override (probabilmente a causa degli attributi di nullabilità).
  • CS8765 - La nullabilità del tipo di parametro non corrisponde al membro sottoposto a override (probabilmente a causa degli attributi di nullabilità).
  • CS8766 - La nullabilità dei tipi riferimento nel tipo di ritorno di non corrisponde al membro implementato in modo implicito (possibilmente a causa degli attributi di nullabilità).
  • CS8767 - La nullabilità dei tipi riferimento nel tipo del parametro non è compatibile con il membro implementato implicitamente (probabilmente a causa degli attributi di nullabilità).
  • CS8768 - La nullabilità dei tipi di riferimento nel tipo restituito non corrisponde al membro implementato (probabilmente a causa di attributi di nullabilità).
  • CS8769 - La nullabilità dei tipi di riferimento nel tipo del parametro non corrisponde al membro implementato (probabilmente a causa degli attributi di nullabilità).
  • CS8770 - Il metodo non dispone dell'annotazione [DoesNotReturn]per corrispondere al membro implementato o sovrascritto.
  • CS8774 - Il membro deve avere un valore non nullo al momento dell'uscita.
  • CS8776 - Il membro non può essere utilizzato in questo attributo.
  • CS8775 - Il membro deve avere un valore diverso da null all'uscita.
  • CS8777 - Il parametro deve avere un valore non Null quando si esce.
  • CS8819 - Il supporto dei valori Null dei tipi riferimento nel tipo restituito non corrisponde alla dichiarazione di metodo parziale.
  • CS8824 - Il parametro deve avere un valore non Null quando si esce perché il parametro è diverso da null.
  • CS8825 - Il valore restituito deve essere non Null perché il parametro è non Null.
  • CS8847 - L'espressione switch non gestisce alcuni input Null (non è esaustivo). Tuttavia, un criterio con una clausola 'when' potrebbe corrispondere correttamente a questo valore.

Nota

L'analisi statica non può sempre dedurre in quale ordine, in uno scenario specifico, si accede ai metodi e se il metodo viene completato correttamente senza generare un'eccezione. Queste insidie note sono ben descritte nella sezione insidie note .

È possibile risolvere quasi tutti gli avvisi usando una delle cinque tecniche seguenti:

  • Configurazione del contesto annullabile.
  • Aggiunta dei controlli di nullità necessari.
  • Aggiunta o rimozione delle annotazioni nullable ? o !.
  • Aggiunta di attributi che descrivono la semantica del null.
  • Inizializzazione corretta delle variabili.

Se non si ha familiarità con l'uso di tipi di riferimento annullabili, la panoramica dei tipi di riferimento annullabili offre una panoramica su cosa risolvono e come funzionano per generare avvisi per possibili errori nel codice. È anche possibile controllare le indicazioni su la migrazione ai tipi di riferimento nullable per saperne di più sul consentire i tipi di riferimento nullable in un progetto esistente.

Configurare il contesto annullabile (nullable)

Gli avvisi seguenti indicano che non è stato impostato correttamente il contesto nullable:

  • CS8632 - L'annotazione per i tipi di riferimento nullable deve essere utilizzata esclusivamente all'interno del codice in un contesto di annotazioni #nullable.
  • cs8636 - opzione non valida per /nullable; deve essere disable, enable, warnings o annotations
  • CS8637 - previsto enable, disableo restore

Sintassi dell'annotazione non corretta

Questi errori e avvisi indicano che l'utilizzo della ! o ? annotazione non è corretta.

  • CS8598 - L'operatore di eliminazione non è consentito in questo contesto
  • CS8623 - 'applicazione esplicita di System.Runtime.CompilerServices.NullableAttribute non è consentita.
  • - CS8628 Non è possibile utilizzare un tipo di riferimento nullable nella creazione dell'oggetto.
  • CS8639 - L'operatore typeof non può essere usato su un tipo di riferimento Nullable

L'annotazione ? in una dichiarazione indica che la variabile potrebbe essere Null. Non indica un tipo di runtime diverso. Entrambe le dichiarazioni seguenti sono lo stesso tipo di runtime:

string s1 = "a string";
string? s2 = "another string";

Il ? è un suggerimento per il compilatore riguardo alle aspettative per i valori null.

L'annotazione ! su un'espressione indica che sei consapevole che l'espressione è sicura e deve essere considerata non nulla.

  • È necessario usare queste annotazioni, non il System.Runtime.CompilerServices.NullableAttribute nel codice.
  • Poiché il ? è un'annotazione, non un tipo, non è possibile usarlo con typeofo new espressioni.
  • L'operatore ! non può essere applicato a un'espressione di variabile o a un gruppo di metodi.
  • L'operatore ! non può essere applicato a sinistra di un operatore di accesso ai membri, ad esempio obj.Field!.Method().

Possibile dereferenziazione di null

Questo set di avvisi avvisa che si sta dereferenziando una variabile il cui stato null è forse null. Questi avvisi sono:

  • CS8602 - Dereferenziamento di un riferimento che potrebbe essere null.
  • CS8670 - L'inizializzatore di oggetto o di collezione deferenzia in modo implicito un membro che potrebbe essere nullo.

Il codice seguente illustra un esempio di ognuno degli avvisi precedenti:

class Container
{
    public List<string>? States { get; set; }
}

internal void PossibleDereferenceNullExamples(string? message)
{
    Console.WriteLine(message.Length); // CS8602

    var c = new Container { States = { "Red", "Yellow", "Green" } }; // CS8670
}

Nell'esempio precedente, l'avviso è dovuto al fatto che l'Container, c, potrebbe avere un valore Null per la proprietà States. L'assegnazione di nuovi stati a una raccolta che potrebbe essere null provoca l'avviso.

Per rimuovere questi avvisi, è necessario aggiungere codice per modificare lo stato null della variabile in non Null prima di dereferenziarlo. L'avviso dell'inizializzatore di raccolta può essere più difficile da individuare. Il compilatore rileva che la raccolta potrebbe essere Null quando l'inizializzatore vi aggiunge elementi.

In molti casi, è possibile correggere questi avvisi controllando che una variabile non sia Null prima di dereferenziarla. Si consideri l'esempio seguente che aggiunge un controllo Null prima di dereferenziare il parametro message:

void WriteMessageLength(string? message)
{
    if (message is not null)
    {
        Console.WriteLine(message.Length);
    }
    
}

Nell'esempio seguente viene inizializzata la memoria di supporto per States e viene rimosso il metodo accessor set. I consumatori della classe possono modificare il contenuto della raccolta e lo spazio di archiviazione della raccolta non è mai null:

class Container
{
    public List<string> States { get; } = new();
}

In altri casi, quando vengono visualizzati questi avvisi potrebbero essere dei falsi positivi. Potresti avere un metodo di utilità privato che controlla la presenza di valori null. Il compilatore non sa che il metodo fornisce un controllo Null. Si consideri l'esempio seguente che usa un metodo di utilità privata, IsNotNull:

public void WriteMessage(string? message)
{
    if (IsNotNull(message))
        Console.WriteLine(message.Length);
}

Il compilatore avvisa che è possibile dereferenziare null quando si scrive la proprietà message.Length perché l'analisi statica determina che message potrebbe essere null. Si sa che IsNotNull fornisce un controllo Null e quando restituisce true, il dello stato Null di message deve essere non null. È necessario indicare al compilatore tali fatti. Un modo consiste nell'usare l'operatore di null forgiving, !. È possibile modificare l'istruzione WriteLine in modo che corrisponda al codice seguente:

Console.WriteLine(message!.Length);

L'operatore di tolleranza Null rende l'espressione non Null, anche se era possibilmente Null senza l'operatore ! applicato. In questo esempio, una soluzione migliore consiste nell'aggiungere un attributo alla firma di IsNotNull:

private static bool IsNotNull([NotNullWhen(true)] object? obj) => obj != null;

System.Diagnostics.CodeAnalysis.NotNullWhenAttribute informa il compilatore che l'argomento utilizzato per il parametro obj è non Null quando il metodo restituisce true. Quando il metodo restituisce false, l'argomento ha lo stesso stato Null che aveva prima della chiamata al metodo.

Suggerimento

È disponibile un set completo di attributi che è possibile usare per descrivere il modo in cui i metodi e le proprietà influiscono sullo stato Null. Per informazioni su di essi, vedere l'articolo di riferimento sul linguaggio sugli attributi di analisi statica che ammettono i valori Null.

La correzione di un avviso per la dereferenziazione di una variabile forse Null prevede una delle tre tecniche seguenti:

  • Aggiungere un controllo Null mancante.
  • Aggiungere attributi di analisi Null nelle API per influire sull'analisi statica dello stato Null del compilatore. Questi attributi informano il compilatore quando un valore restituito o un argomento deve essere forse null o non null dopo aver chiamato il metodo.
  • Applicare l'operatore di eliminazione dei null ! all'espressione che impone lo stato come non null.

Possibile valore Null assegnato a un riferimento non nullable

Questo set di avvisi segnala che si sta assegnando una variabile il cui tipo è non annullabile a un'espressione il cui stato null è forse nullo. Questi avvisi sono:

  • CS8597 - Il valore generato può essere Null.
  • CS8600 - Conversione di valori letterali Null o possibile Null in un tipo che non ammette i valori Null.
  • CS8601 - Possibile assegnazione di riferimento Null.
  • CS8603 - Possibile restituzione di riferimento null.
  • CS8604 - Argomento di riferimento Null possibile per il parametro.
  • CS8605 - Effettuando unboxing di un valore che potrebbe essere null.
  • CS8625 - Non è possibile convertire un valore letterale Null in un tipo riferimento che non ammette i valori Null.
  • CS8629 - Il tipo valore nullable potrebbe essere null.

Il compilatore genera questi avvisi quando si tenta di assegnare un'espressione che è potenzialmente nullo a una variabile che non è annullabile. Ad esempio:

string? TryGetMessage(int id) => "";

string msg = TryGetMessage(42);  // Possible null assignment.

I diversi avvisi indicano informazioni dettagliate sul codice, ad esempio assegnazione, assegnazione di unboxing, dichiarazioni di ritorno, argomenti ai metodi e espressioni di lancio.

È possibile eseguire una delle tre azioni per risolvere questi avvisi. Uno consiste nell'aggiungere l'annotazione ? per rendere la variabile un tipo riferimento nullable. Questa modifica può causare altri avvisi. La modifica di una variabile da un riferimento che non ammette i valori Null a un riferimento che ammette i valori Null modifica il relativo stato Null predefinito da non Null a forse Null. L'analisi statica del compilatore trova istanze in cui si dereferenzia una variabile forse null.

Le altre azioni indicano al compilatore che il lato destro dell'assegnazione è non Null. L'espressione nella parte destra potrebbe essere controllata per null prima dell'assegnazione, come illustrato nell'esempio seguente:

string notNullMsg = TryGetMessage(42) ?? "Unknown message id: 42";

Negli esempi precedenti viene illustrata l'assegnazione del valore restituito di un metodo. Annotare il metodo (o la proprietà) per indicare quando un metodo restituisce un valore diverso da Null. Spesso System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute specifica che un valore restituito è non Null quando un argomento di input è non Null. Un'altra alternativa consiste nell'aggiungere l'operatore di null forgiving, ! alla destra.

string msg = TryGetMessage(42)!;

La correzione di un avviso per l'assegnazione di un'espressione forse Null a una variabile non Null prevede una delle quattro tecniche seguenti:

  • Modificare il lato sinistro dell'assegnazione in un tipo annullabile. Questa azione può introdurre nuovi avvisi quando si dereferenzia tale variabile.
  • Effettuare un controllo per valori nulli prima dell'assegnazione.
  • Annotare l'API che produce la parte destra dell'assegnamento.
  • Aggiungere l'operatore di perdono null alla destra dell'assegnazione.

Riferimento non annullabile non inizializzato

Questo insieme di avvisi segnala che si sta assegnando una variabile il cui tipo è non annullabile a un'espressione il cui stato nullo è potenzialmente nullo. Questi avvisi sono:

  • CS8618 - La variabile non annullabile deve contenere un valore non null all'uscita dal costruttore. Valutare la possibilità di dichiararla come annullabile.
  • CS8762 - Il parametro deve avere un valore non Null quando si esce.

Si consideri la classe seguente come esempio:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

FirstNameLastName sono inizializzati con garanzia. Se questo codice è nuovo, è consigliabile modificare l'interfaccia pubblica. L'esempio precedente può essere aggiornato come segue:

public class Person
{
    public Person(string first, string last)
    {
        FirstName = first;
        LastName = last;
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Se è necessario creare un oggetto Person prima di impostare il nome, è possibile inizializzare le proprietà usando un valore non Null predefinito:

public class Person
{
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
}

Un'altra alternativa consiste nel modificare tali membri in tipi di riferimento nullable. La classe Person può essere definita come segue se null deve essere consentita per il nome:

public class Person
{
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
}

Il codice esistente talvolta richiede altre modifiche per informare il compilatore sulla semantica Null per tali membri. Potrebbe avere più costruttori e la tua classe ha un metodo ausiliario privato che inizializza uno o più membri. È possibile spostare il codice di inizializzazione in un singolo costruttore e assicurarsi che tutti i costruttori chiamino quello con il codice di inizializzazione comune. In alternativa, è possibile usare gli attributi System.Diagnostics.CodeAnalysis.MemberNotNullAttribute e System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute. Questi attributi informano il compilatore che un membro è non Null dopo che il metodo restituisce. Il codice seguente visualizza un esempio con ogni metodo. La classe Person usa un costruttore comune chiamato da tutti gli altri costruttori. La classe Student ha un metodo helper annotato con l'attributo System.Diagnostics.CodeAnalysis.MemberNotNullAttribute:


using System.Diagnostics.CodeAnalysis;

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }

    public Person() : this("John", "Doe") { }
}

public class Student : Person
{
    public string Major { get; set; }

    public Student(string firstName, string lastName, string major)
        : base(firstName, lastName)
    {
        SetMajor(major);
    }

    public Student(string firstName, string lastName) :
        base(firstName, lastName)
    {
        SetMajor();
    }

    public Student()
    {
        SetMajor();
    }

    [MemberNotNull(nameof(Major))]
    private void SetMajor(string? major = default)
    {
        Major = major ?? "Undeclared";
    }
}

Infine, è possibile usare l'operatore null forgiving per indicare che un membro viene inizializzato in un altro codice. Per un altro esempio, considerare le classi seguenti che rappresentano un modello Entity Framework Core:

public class TodoItem
{
    public long Id { get; set; }
    public string? Name { get; set; }
    public bool IsComplete { get; set; }
}

public class TodoContext : DbContext
{
    public TodoContext(DbContextOptions<TodoContext> options)
        : base(options)
    {
    }

    public DbSet<TodoItem> TodoItems { get; set; } = null!;
}

La proprietà DbSet viene inizializzata su null!. Indica al compilatore che la proprietà è impostata su un valore da non Null. Infatti, la base DbContext esegue l'inizializzazione del set. L'analisi statica del compilatore non lo rileva. Per altre informazioni sull'uso dei tipi riferimento nullable e di Entity Framework Core, vedere l'articolo Uso di tipi di riferimento nullable in EF Core.

La correzione di un avviso per non inizializzare un membro non annullabile prevede una delle quattro tecniche seguenti:

  • Modificare i costruttori o gli inizializzatori di campo per garantire che tutti i membri non nullable siano inizializzati.
  • Modificare uno o più membri in modo che siano tipi annullabili.
  • Annotare qualsiasi metodo helper per indicare quali membri vengono assegnati.
  • Aggiungere un inizializzatore a null! per indicare che il membro viene inizializzato in altro codice.

Dichiarazione di mancata corrispondenza di nullabilità

Molti avvisi indicano la mancata corrispondenza dei valori Null tra le firme per metodi, delegati o parametri di tipo.

  • CS8608 - La nullabilità dei tipi riferimento nel tipo non corrisponde a quella del membro sovrascritto.
  • CS8609 - La nullabilità dei tipi riferimento nel tipo di ritorno non corrisponde al membro sottoposto a ridefinizione.
  • CS8610 - La nullabilità dei tipi di riferimento nel parametro di tipo non corrisponde al membro sovrascritto.
  • CS8611 - La nullabilità dei tipi di riferimento nel parametro di tipo non corrisponde alla dichiarazione del metodo parziale.
  • CS8612 - La nullabilità dei tipi riferimento nel tipo non corrisponde al membro implementato implicitamente.
  • CS8613 - La nullabilità dei tipi di riferimento nel tipo restituito non corrisponde a quella del membro implementato implicitamente.
  • CS8614 - La nullabilità dei tipi di riferimento nel tipo del parametro non corrisponde al membro implementato implicitamente.
  • CS8615 - La nullabilità dei tipi di riferimento nel tipo non corrisponde al membro implementato.
  • CS8616 - La nullabilità dei tipi di riferimento nel tipo di ritorno non corrisponde al membro implementato.
  • CS8617 - La nullabilità dei tipi di riferimento nel tipo di parametro non corrisponde al membro implementato.
  • CS8619 - La nullabilità dei tipi riferimento nei valori non corrisponde al tipo di destinazione.
  • CS8620 - L'argomento non può essere usato per il parametro a causa di differenze nella nullabilità dei tipi di riferimento.
  • CS8621 - La nullabilità dei tipi riferimento nel tipo restituito non coincide con il delegato di destinazione (probabilmente a causa di attributi di nullabilità).
  • CS8622 - La nullabilità dei tipi di riferimento nel tipo di un parametro non corrisponde al delegato di destinazione (forse a causa di attributi di nullabilità).
  • CS8624 - L'argomento non può essere usato come output a causa di differenze nella nullabilità dei tipi di riferimento.
  • CS8631 - Il tipo non può essere utilizzato come parametro nel tipo o metodo generico. La nullabilità dell'argomento non corrisponde ai vincoli del tipo.
  • CS8633 - La nullabilità nei vincoli per il parametro di tipo del metodo non corrisponde ai vincoli per il parametro di tipo del metodo dell'interfaccia. Provare a usare un'implementazione esplicita dell'interfaccia.
  • CS8634 - Il tipo non può essere utilizzato come parametro di tipo nel tipo o nel metodo generico. La nullabilità dell'argomento di tipo non soddisfa il vincolo 'class'.
  • CS8643 - La nullabilità dei tipi di riferimento nello specificatore di interfaccia esplicito non corrisponde all'interfaccia implementata dal tipo.
  • CS8644 - Il tipo non implementa il membro dell'interfaccia. La nullabilità dei tipi di riferimento nell'interfaccia implementata dal tipo di base non corrisponde.
  • CS8645 - Il membro è già elencato nella lista dell'interfaccia del tipo con diversa nullabilità dei tipi di riferimento.
  • CS8667 - Le dichiarazioni di metodi parziali hanno nullabilità incoerente nei vincoli del parametro di tipo.
  • CS8714 - Il tipo non può essere usato come parametro di tipo nel tipo o nel metodo generico. La nullabilità dell'argomento di tipo non corrisponde al vincolo 'non null'.
  • CS8764 - La nullabilità del tipo restituito non corrisponde al membro sottoposto a override (probabilmente a causa di attributi di nullabilità).
  • CS8765 - La nullabilità del tipo del parametro non corrisponde a quella del membro sottoposto a override (probabilmente a causa degli attributi di nullabilità).
  • CS8766 - La nullabilità dei tipi di riferimento nel tipo restituito non corrisponde al membro implementato implicitamente (possibilmente a causa di attributi di nullabilità).
  • CS8767 - La nullabilità dei tipi riferimento nel tipo di parametro non corrisponde al membro implementato implicitamente (probabilmente a causa di attributi di nullabilità).
  • CS8768 - La nullabilità dei tipi riferimento nel tipo di ritorno non corrisponde al membro implementato (probabilmente a causa di attributi di nullabilità).
  • CS8769 - La nullabilità dei tipi di riferimento nel parametro non corrisponde al membro implementato (probabilmente a causa di attributi della nullabilità).
  • CS8819 - La nullabilità dei tipi di riferimento nel tipo restituito non corrisponde alla dichiarazione del metodo parziale.

Il codice seguente illustra CS8764:

public class B
{
    public virtual string GetMessage(string id) => string.Empty;
}
public class D : B
{
    public override string? GetMessage(string? id) => default;
}

L'esempio precedente mostra un metodo virtual in una classe di base e un oggetto override con supporto dei valori Null diverso. La classe base restituisce una stringa non nullabile, ma la classe derivata restituisce una stringa nullabile. Se string e string? sono invertiti, sarebbe consentito perché la classe derivata è più restrittiva. Analogamente, le dichiarazioni dei parametri devono corrispondere. I parametri nel metodo di override possono consentire null anche quando la classe base non lo fa.

Altre situazioni possono generare questi avvisi. Si ha una mancata corrispondenza in una dichiarazione di metodo di interfaccia e l'implementazione di tale metodo. Oppure un tipo delegato e l'espressione per tale delegato differiscono. La differenza tra un parametro di tipo e un argomento di tipo è nella nullabilità.

Per correggere questi avvisi, aggiornare la dichiarazione appropriata.

Il codice non corrisponde alla dichiarazione dell'attributo

Nelle sezioni precedenti è stato illustrato come usare attributi per l'analisi statica nullable per informare il compilatore sulla semantica Null del codice. Il compilatore avvisa se il codice non rispetta le promesse di tale attributo:

  • CS8607 - Un possibile valore Null non può essere usato per un tipo contrassegnato con [NotNull] o [DisallowNull]
  • CS8763 - Un metodo contrassegnato [DoesNotReturn] non deve restituire.
  • CS8770 - Il metodo non dispone dell'annotazione [DoesNotReturn] per corrispondere al membro implementato o sottoposto a override.
  • CS8774 - Il membro deve avere un valore non nullo quando si esce.
  • CS8775 - Il membro deve avere un valore non Null quando si esce.
  • CS8776 - Il membro non può essere utilizzato in questo attributo.
  • CS8777 - Il parametro deve avere un valore non Null quando si esce.
  • CS8824 - Il parametro deve avere un valore non Null quando si esce perché il parametro è non null.
  • CS8825 - Il valore restituito deve essere non null perché il parametro è non null.

Si consideri il modello seguente:

public bool TryGetMessage(int id, [NotNullWhen(true)] out string? message)
{
    message = null;
    return true;

}

Il compilatore genera un avviso perché il parametro message è assegnato nulle il metodo restituisce true. L'attributo NotNullWhen indica che non deve verificarsi.

Per risolvere questi avvisi, aggiornare il codice in modo che corrisponda alle aspettative degli attributi applicati. È possibile modificare gli attributi o l'algoritmo .

Espressione switch esaustiva

Le espressioni switch devono essere esaustive, ovvero tutti i valori di input devono essere gestiti. Anche per i tipi riferimento che non ammettono i valori Null, il valore null deve essere tenuto in considerazione. Il compilatore genera avvisi quando il valore Null non viene gestito:

  • CS8655 - L'espressione switch non gestisce alcuni input null (non è completa).
  • CS8847 - L'espressione switch non gestisce alcuni input Null (non è esaustivo). Tuttavia, un criterio con una clausola 'when' potrebbe corrispondere correttamente a questo valore.

Il codice di esempio seguente illustra questa condizione:

int AsScale(string status) =>
    status switch
    {
        "Red" => 0,
        "Yellow" => 5,
        "Green" => 10,
        { } => -1
    };

L'espressione di input è un oggetto string, non un oggetto string?. Il compilatore genera comunque questo avviso. Il criterio { } gestisce tutti i valori non Null, ma non corrisponde a null. Per risolvere questi errori, è possibile aggiungere un caso null esplicito o sostituire { } con il modello (discard) _. Il modello di scarto corrisponde a null oltre a qualsiasi altro valore.