Gli attributi riservati contribuiscono all'analisi statica dello stato null del compilatoreReserved attributes contribute to the compiler's null state static analysis

In un contesto Nullable, il compilatore esegue l'analisi statica del codice per determinare lo stato null di tutte le variabili di tipo riferimento:In a nullable context, the compiler performs static analysis of code to determine the null state of all reference type variables:

  • not null: l'analisi statica determina che a una variabile viene assegnato un valore non null.not null: Static analysis determines that a variable is assigned a non-null value.
  • forse null: l'analisi statica non può determinare che a una variabile è assegnato un valore non null.maybe null: Static analysis can't determine that a variable is assigned a non-null value.

È possibile applicare attributi che forniscono informazioni al compilatore sulla semantica delle API.You can apply attributes that provide information to the compiler about the semantics of your APIs. Tali informazioni consentono al compilatore di eseguire analisi statiche e determinare quando una variabile non è null.That information helps the compiler perform static analysis and determine when a variable isn't null. In questo articolo viene fornita una breve descrizione di ognuno di questi attributi e viene illustrato come usarli.This article provides a brief description of each of those attributes and how to use them. Tutti gli esempi presuppongono C# 8,0 o versione successiva e il codice si trova in un contesto Nullable.All the examples assume C# 8.0 or newer, and the code is in a nullable context.

Iniziamo con un esempio familiare.Let's start with a familiar example. Si supponga che la libreria disponga dell'API seguente per recuperare una stringa di risorsa:Imagine your library has the following API to retrieve a resource string:

bool TryGetMessage(string key, out string message)

L'esempio precedente segue il Try* modello familiare in .NET.The preceding example follows the familiar Try* pattern in .NET. Per questa API sono disponibili due argomenti di riferimento: key e message .There are two reference arguments for this API: the key and the message parameter. Questa API presenta le regole seguenti relative al valore null di questi argomenti:This API has the following rules relating to the nullness of these arguments:

  • I chiamanti non devono passare null come argomento per key .Callers shouldn't pass null as the argument for key.
  • I chiamanti possono passare una variabile il cui valore è null come argomento per message .Callers can pass a variable whose value is null as the argument for message.
  • Se il TryGetMessage metodo restituisce true , il valore di message non è null.If the TryGetMessage method returns true, the value of message isn't null. Se il valore restituito è false, il valore di message (e il relativo stato null) è null.If the return value is false, the value of message (and its null state) is null.

La regola per key può essere espressa dal tipo di variabile: key deve essere un tipo di riferimento non nullable.The rule for key can be expressed by the variable type: key should be a non-nullable reference type. Il message parametro è più complesso.The message parameter is more complex. Consente null come argomento, ma garantisce che, in seguito all'esito positivo, l' out argomento non sia null.It allows null as the argument, but guarantees that, on success, that out argument isn't null. Per questi scenari, è necessario un vocabolario più completo per descrivere le aspettative.For these scenarios, you need a richer vocabulary to describe the expectations.

Sono stati aggiunti diversi attributi per esprimere informazioni aggiuntive sullo stato null delle variabili.Several attributes have been added to express additional information about the null state of variables. Tutto il codice scritto prima di C# 8 ha introdotto tipi di riferimento Nullable è un valore null ignaro.All code you wrote before C# 8 introduced nullable reference types was null oblivious. Ciò significa che qualsiasi variabile di tipo riferimento può essere null, ma non sono necessari controlli null.That means any reference type variable may be null, but null checks aren't required. Quando il codice ammette i valori null, tali regole cambiano.Once your code is nullable aware, those rules change. I tipi di riferimento non devono mai essere il null valore e i tipi di riferimento nullable devono essere controllati null prima di essere dereferenziati.Reference types should never be the null value, and nullable reference types must be checked against null before being dereferenced.

Le regole per le API sono probabilmente più complesse, come si è visto con lo TryGetValue scenario API.The rules for your APIs are likely more complicated, as you saw with the TryGetValue API scenario. Molte API hanno regole più complesse quando le variabili possono o non possono essere null .Many of your APIs have more complex rules for when variables can or can't be null. In questi casi, si userà uno degli attributi seguenti per esprimere queste regole:In these cases, you'll use one of the following attributes to express those rules:

  • AllowNull: un argomento di input che non ammette i valori null può essere null.AllowNull: A non-nullable input argument may be null.
  • DisallowNull: un argomento di input nullable non deve mai essere null.DisallowNull: A nullable input argument should never be null.
  • MaybeNull: un valore restituito non nullable può essere null.MaybeNull: A non-nullable return value may be null.
  • NotNull: un valore restituito nullable non sarà mai null.NotNull: A nullable return value will never be null.
  • MaybeNullWhen: un argomento di input che non ammette i valori null può essere null quando il metodo restituisce il bool valore specificato.MaybeNullWhen: A non-nullable input argument may be null when the method returns the specified bool value.
  • NotNullWhen: un argomento di input nullable non sarà null quando il metodo restituisce il bool valore specificato.NotNullWhen: A nullable input argument won't be null when the method returns the specified bool value.
  • NotNullIfNotNull: un valore restituito non è null se l'argomento per il parametro specificato non è null.NotNullIfNotNull: A return value isn't null if the argument for the specified parameter isn't null.
  • DoesNotReturn: un metodo non restituisce mai.DoesNotReturn: A method never returns. In altre parole, genera sempre un'eccezione.In other words, it always throws an exception.
  • DoesNotReturnIf: questo metodo non restituisce mai se il bool valore specificato per il parametro associato è.DoesNotReturnIf: This method never returns if the associated bool parameter has the specified value.
  • MemberNotNull: il membro elencato non sarà null quando il metodo restituisce.MemberNotNull: The listed member won't be null when the method returns.
  • MemberNotNullWhen: il membro elencato non sarà null quando il metodo restituisce il bool valore specificato.MemberNotNullWhen: The listed member won't be null when the method returns the specified bool value.

Le descrizioni precedenti sono un riferimento rapido a ogni attributo.The preceding descriptions are a quick reference to what each attribute does. Ogni sezione seguente descrive il comportamento e il significato più approfondito.Each following section describes the behavior and meaning more thoroughly.

L'aggiunta di questi attributi offre al compilatore ulteriori informazioni sulle regole per l'API.Adding these attributes gives the compiler more information about the rules for your API. Quando il codice chiamante viene compilato in un contesto abilitato Nullable, il compilatore avvisa i chiamanti quando violano tali regole.When calling code is compiled in a nullable enabled context, the compiler will warn callers when they violate those rules. Questi attributi non consentono ulteriori controlli sull'implementazione.These attributes don't enable more checks on your implementation.

Specificare le precondizioni: AllowNull e DisallowNullSpecify preconditions: AllowNull and DisallowNull

Si consideri una proprietà di lettura/scrittura che non restituisce mai null perché ha un valore predefinito ragionevole.Consider a read/write property that never returns null because it has a reasonable default value. I chiamanti passano null alla funzione di accesso set quando vengono impostati su tale valore predefinito.Callers pass null to the set accessor when setting it to that default value. Si consideri, ad esempio, un sistema di messaggistica che richiede un nome di schermata in una chat room.For example, consider a messaging system that asks for a screen name in a chat room. Se non viene specificato alcun valore, il sistema genera un nome casuale:If none is provided, the system generates a random name:

public string ScreenName
{
   get => _screenName;
   set => _screenName = value ?? GenerateRandomScreenName();
}
private string _screenName;

Quando si compila il codice precedente in un contesto ignaro Nullable, tutto funziona correttamente.When you compile the preceding code in a nullable oblivious context, everything is fine. Quando si abilitano i tipi di riferimento Nullable, la ScreenName proprietà diventa un riferimento che non ammette i valori null.Once you enable nullable reference types, the ScreenName property becomes a non-nullable reference. Questo è corretto per la get funzione di accesso: non restituisce mai null .That's correct for the get accessor: it never returns null. I chiamanti non devono controllare la proprietà restituita per null .Callers don't need to check the returned property for null. Ma ora impostando la proprietà su viene null generato un avviso.But now setting the property to null generates a warning. Per supportare questo tipo di codice, aggiungere l' System.Diagnostics.CodeAnalysis.AllowNullAttribute attributo alla proprietà, come illustrato nel codice seguente:To support this type of code, you add the System.Diagnostics.CodeAnalysis.AllowNullAttribute attribute to the property, as shown in the following code:

[AllowNull]
public string ScreenName
{
   get => _screenName;
   set => _screenName = value ?? GenerateRandomScreenName();
}
private string _screenName = GenerateRandomScreenName();

Potrebbe essere necessario aggiungere una using direttiva per System.Diagnostics.CodeAnalysis per usare questo e altri attributi descritti in questo articolo.You may need to add a using directive for System.Diagnostics.CodeAnalysis to use this and other attributes discussed in this article. L'attributo viene applicato alla proprietà, non alla set funzione di accesso.The attribute is applied to the property, not the set accessor. L' AllowNull attributo specifica le condizioni preliminari e si applica solo agli input.The AllowNull attribute specifies pre-conditions, and only applies to inputs. La get funzione di accesso ha un valore restituito, ma nessun argomento di input.The get accessor has a return value, but no input arguments. Pertanto, l' AllowNull attributo si applica solo alla set funzione di accesso.Therefore, the AllowNull attribute only applies to the set accessor.

Nell'esempio precedente viene illustrato cosa cercare quando si aggiunge l' AllowNull attributo in un argomento:The preceding example demonstrates what to look for when adding the AllowNull attribute on an argument:

  1. Il contratto generale per tale variabile è che non deve essere null , pertanto si desidera un tipo di riferimento non nullable.The general contract for that variable is that it shouldn't be null, so you want a non-nullable reference type.
  2. Esistono scenari per la variabile di input null , sebbene non siano l'utilizzo più comune.There are scenarios for the input variable to be null, though they aren't the most common usage.

Spesso è necessario questo attributo per le proprietà, gli in argomenti, out e ref .Most often you'll need this attribute for properties, or in, out, and ref arguments. L' AllowNull attributo è la scelta migliore quando una variabile è in genere non null, ma è necessario consentirla null come precondizione.The AllowNull attribute is the best choice when a variable is typically non-null, but you need to allow null as a precondition.

Si confronti con gli scenari per l'utilizzo di DisallowNull : si utilizza questo attributo per specificare che una variabile di input di un tipo di riferimento nullable non deve essere null .Contrast that with scenarios for using DisallowNull: You use this attribute to specify that an input variable of a nullable reference type shouldn't be null. Si consideri una proprietà null in cui è il valore predefinito, ma i client possono impostarlo solo su un valore non null.Consider a property where null is the default value, but clients can only set it to a non-null value. Osservare il codice seguente:Consider the following code:

public string ReviewComment
{
    get => _comment;
    set => _comment = value ?? throw new ArgumentNullException(nameof(value), "Cannot set to null");
}
string _comment;

Il codice precedente rappresenta il modo migliore per esprimere la progettazione che ReviewComment può essere null , ma non può essere impostato su null .The preceding code is the best way to express your design that the ReviewComment could be null, but can't be set to null. Una volta che il codice ammette i valori null, è possibile esprimere questo concetto in modo più chiaro ai chiamanti utilizzando System.Diagnostics.CodeAnalysis.DisallowNullAttribute :Once this code is nullable aware, you can express this concept more clearly to callers using the System.Diagnostics.CodeAnalysis.DisallowNullAttribute:

[DisallowNull]
public string? ReviewComment
{
    get => _comment;
    set => _comment = value ?? throw new ArgumentNullException(nameof(value), "Cannot set to null");
}
string? _comment;

In un contesto Nullable la ReviewComment get funzione di accesso può restituire il valore predefinito null .In a nullable context, the ReviewComment get accessor could return the default value of null. Il compilatore avverte che è necessario verificarlo prima dell'accesso.The compiler warns that it must be checked before access. Inoltre, avvisa i chiamanti che, anche se potrebbero essere, i null chiamanti non devono impostarlo in modo esplicito su null .Furthermore, it warns callers that, even though it could be null, callers shouldn't explicitly set it to null. L' DisallowNull attributo specifica anche una condizione preliminare, non influisce sulla get funzione di accesso.The DisallowNull attribute also specifies a pre-condition, it doesn't affect the get accessor. Usare l' DisallowNull attributo quando si osservano queste caratteristiche:You use the DisallowNull attribute when you observe these characteristics about:

  1. La variabile potrebbe trovarsi null negli scenari principali, spesso quando viene creata per la prima volta.The variable could be null in core scenarios, often when first instantiated.
  2. La variabile non deve essere impostata in modo esplicito su null .The variable shouldn't be explicitly set to null.

Queste situazioni sono comuni nel codice che originariamente era null ignaro.These situations are common in code that was originally null oblivious. È possibile che le proprietà dell'oggetto siano impostate in due operazioni di inizializzazione distinte.It may be that object properties are set in two distinct initialization operations. È possibile che alcune proprietà siano impostate solo dopo il completamento di alcune operazioni asincrone.It may be that some properties are set only after some asynchronous work has completed.

Gli AllowNull DisallowNull attributi e consentono di specificare che le precondizioni sulle variabili potrebbero non corrispondere alle annotazioni Nullable di tali variabili.The AllowNull and DisallowNull attributes enable you to specify that preconditions on variables may not match the nullable annotations on those variables. Sono disponibili informazioni più dettagliate sulle caratteristiche dell'API.These provide more detail about the characteristics of your API. Queste informazioni aggiuntive consentono ai chiamanti di usare correttamente l'API.This additional information helps callers use your API correctly. Ricordare di specificare le precondizioni usando gli attributi seguenti:Remember you specify preconditions using the following attributes:

  • AllowNull: un argomento di input che non ammette i valori null può essere null.AllowNull: A non-nullable input argument may be null.
  • DisallowNull: un argomento di input nullable non deve mai essere null.DisallowNull: A nullable input argument should never be null.

Specificare le post-conditions: MaybeNull e NotNullSpecify post-conditions: MaybeNull and NotNull

Si supponga di avere un metodo con la firma seguente:Suppose you have a method with the following signature:

public Customer FindCustomer(string lastName, string firstName)

Probabilmente è stato scritto un metodo come questo per restituire null quando il nome cercato non è stato trovato.You've likely written a method like this to return null when the name sought wasn't found. nullIndica chiaramente che il record non è stato trovato.The null clearly indicates that the record wasn't found. In questo esempio è probabile che si modifichi il tipo restituito da Customer a Customer? .In this example, you'd likely change the return type from Customer to Customer?. La dichiarazione del valore restituito come tipo di riferimento Nullable specifica lo scopo di questa API in modo chiaro.Declaring the return value as a nullable reference type specifies the intent of this API clearly.

Per motivi trattati in definizioni generiche e supporto di valori null, la tecnica non funziona con i metodi generici.For reasons covered under Generic definitions and nullability that technique doesn't work with generic methods. È possibile che si disponga di un metodo generico che segue un modello simile:You may have a generic method that follows a similar pattern:

public T Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate)

Non è possibile specificare che il valore restituito è T? .You can't specify that the return value is T?. Il metodo restituisce null quando l'elemento cercato non viene trovato.The method returns null when the sought item isn't found. Poiché non è possibile dichiarare un T? tipo restituito, è necessario aggiungere l' MaybeNull annotazione al metodo restituito:Since you can't declare a T? return type, you add the MaybeNull annotation to the method return:

[return: MaybeNull]
public T Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate)

Il codice precedente informa i chiamanti che il contratto implica un tipo non nullable, ma il valore restituito può essere effettivamente null.The preceding code informs callers that the contract implies a non-nullable type, but the return value may actually be null. Usare l' MaybeNull attributo quando l'API deve essere un tipo non nullable, in genere un parametro di tipo generico, ma possono essere presenti istanze in cui null verrebbe restituito.Use the MaybeNull attribute when your API should be a non-nullable type, typically a generic type parameter, but there may be instances where null would be returned.

È anche possibile specificare che un valore restituito o un out ref argomento o non sia null anche se il tipo è un tipo di riferimento Nullable.You can also specify that a return value or an out or ref argument isn't null even though the type is a nullable reference type. Si consideri un metodo che garantisce che una matrice sia sufficientemente grande da mantenere un numero di elementi.Consider a method that ensures an array is large enough to hold a number of elements. Se l'argomento di input non dispone di capacità, la routine alloca una nuova matrice e copia tutti gli elementi esistenti al suo interno.If the input argument doesn't have capacity, the routine would allocate a new array and copy all the existing elements into it. Se l'argomento di input è null , la routine allocherà la nuova risorsa di archiviazione.If the input argument is null, the routine would allocate new storage. Se la capacità è sufficiente, la routine non esegue alcuna operazione:If there's sufficient capacity, the routine does nothing:

public void EnsureCapacity<T>(ref T[] storage, int size)

È possibile chiamare questa routine come segue:You could call this routine as follows:

// messages has the default value (null) when EnsureCapacity is called:
EnsureCapacity<string>(ref messages, 10);
// messages is not null.
EnsureCapacity<string>(messages, 50);

Dopo aver abilitato i tipi di riferimento null, è necessario assicurarsi che il codice precedente venga compilato senza avvisi.After enabling null reference types, you want to ensure that the preceding code compiles without warnings. Quando il metodo restituisce un risultato, l' storage argomento è sicuramente not null.When the method returns, the storage argument is guaranteed to be not null. Tuttavia, è accettabile chiamare EnsureCapacity con un riferimento null.However, it's acceptable to call EnsureCapacity with a null reference. È possibile creare storage un tipo di riferimento nullable e aggiungere la NotNull post-condizione alla dichiarazione del parametro:You can make storage a nullable reference type, and add the NotNull post-condition to the parameter declaration:

public void EnsureCapacity<T>([NotNull] ref T[]? storage, int size)

Il codice precedente esprime chiaramente il contratto esistente: i chiamanti possono passare una variabile con il null valore, ma il valore restituito non è mai null.The preceding code expresses the existing contract clearly: Callers can pass a variable with the null value, but the return value is guaranteed to never be null. L' NotNull attributo è particolarmente utile per ref gli out argomenti e null , dove può essere passato come argomento, ma tale argomento è sicuramente not null quando il metodo restituisce.The NotNull attribute is most useful for ref and out arguments where null may be passed as an argument, but that argument is guaranteed to be not null when the method returns.

È possibile specificare postcondizioni non condizionali usando gli attributi seguenti:You specify unconditional postconditions using the following attributes:

  • MaybeNull: un valore restituito non nullable può essere null.MaybeNull: A non-nullable return value may be null.
  • NotNull: un valore restituito nullable non sarà mai null.NotNull: A nullable return value will never be null.

Specificare le condizioni postali condizionali: NotNullWhen , MaybeNullWhen e NotNullIfNotNullSpecify conditional post-conditions: NotNullWhen, MaybeNullWhen, and NotNullIfNotNull

È probabile che si abbia familiarità con il string metodo String.IsNullOrEmpty(String) .You're likely familiar with the string method String.IsNullOrEmpty(String). Questo metodo restituisce true quando l'argomento è null o una stringa vuota.This method returns true when the argument is null or an empty string. Si tratta di un tipo di controllo null: i chiamanti non devono verificare se il metodo restituisce l'argomento false .It's a form of null-check: Callers don't need to null-check the argument if the method returns false. Per rendere un metodo simile a Nullable, impostare l'argomento su un tipo di riferimento nullable e aggiungere l' NotNullWhen attributo:To make a method like this nullable aware, you'd set the argument to a nullable reference type, and add the NotNullWhen attribute:

bool IsNullOrEmpty([NotNullWhen(false)] string? value);

Che informa il compilatore che il codice in cui il valore restituito non è false necessario per i controlli null.That informs the compiler that any code where the return value is false doesn't need null checks. L'aggiunta dell'attributo informa l'analisi statica del compilatore che IsNullOrEmpty esegue il controllo null necessario: quando restituisce false , l'argomento di input non è null .The addition of the attribute informs the compiler's static analysis that IsNullOrEmpty performs the necessary null check: when it returns false, the input argument isn't null.

string? userInput = GetUserInput();
if (!string.IsNullOrEmpty(userInput))
{
   int messageLength = userInput.Length; // no null check needed.
}
// null check needed on userInput here.

Il String.IsNullOrEmpty(String) metodo verrà annotato come illustrato in precedenza per .NET Core 3,0.The String.IsNullOrEmpty(String) method will be annotated as shown above for .NET Core 3.0. Nella codebase potrebbero essere presenti metodi simili che controllano lo stato degli oggetti per i valori null.You may have similar methods in your codebase that check the state of objects for null values. Il compilatore non riconosce i metodi di controllo null personalizzati ed è necessario aggiungervi le annotazioni.The compiler won't recognize custom null check methods, and you'll need to add the annotations yourself. Quando si aggiunge l'attributo, l'analisi statica del compilatore sa quando la variabile testata è stata verificata come null.When you add the attribute, the compiler's static analysis knows when the tested variable has been null checked.

Un altro uso di questi attributi è il Try* modello.Another use for these attributes is the Try* pattern. Le postcondizioni per ref le out variabili e vengono comunicate tramite il valore restituito.The postconditions for ref and out variables are communicated through the return value. Si consideri questo metodo illustrato in precedenza:Consider this method shown earlier:

bool TryGetMessage(string key, out string message)

Il metodo precedente segue un normale idioma .NET: il valore restituito indica se message è stato impostato sul valore trovato o, se non viene trovato alcun messaggio, al valore predefinito.The preceding method follows a typical .NET idiom: the return value indicates if message was set to the found value or, if no message is found, to the default value. Se il metodo restituisce true , il valore di message non è null; in caso contrario, il metodo imposta message su null.If the method returns true, the value of message isn't null; otherwise, the method sets message to null.

È possibile comunicare tale idioma usando l' NotNullWhen attributo.You can communicate that idiom using the NotNullWhen attribute. Quando si aggiorna la firma per i tipi di riferimento Nullable, creare message un oggetto string? e aggiungere un attributo:When you update the signature for nullable reference types, make message a string? and add an attribute:

bool TryGetMessage(string key, [NotNullWhen(true)] out string? message)

Nell'esempio precedente, il valore di message è noto come not null quando TryGetMessage restituisce true .In the preceding example, the value of message is known to be not null when TryGetMessage returns true. È necessario annotare metodi simili nella codebase nello stesso modo: gli argomenti potrebbero essere null , e sono noti come not null quando il metodo restituisce true .You should annotate similar methods in your codebase in the same way: the arguments could be null, and are known to be not null when the method returns true.

È possibile che sia necessario anche un attributo finale.There's one final attribute you may also need. A volte lo stato null di un valore restituito dipende dallo stato null di uno o più argomenti di input.Sometimes the null state of a return value depends on the null state of one or more input arguments. Questi metodi restituiranno un valore non null ogni volta che determinati argomenti di input non sono null .These methods will return a non-null value whenever certain input arguments aren't null. Per annotare correttamente questi metodi, usare l' NotNullIfNotNull attributo.To correctly annotate these methods, you use the NotNullIfNotNull attribute. Si consideri il seguente metodo:Consider the following method:

string GetTopLevelDomainFromFullUrl(string url);

Se l' url argomento non è null, l'output non è null .If the url argument isn't null, the output isn't null. Una volta abilitati i riferimenti Nullable, la firma funziona correttamente, purché l'API non accetti mai un input null.Once nullable references are enabled, that signature works correctly, provided your API never accepts a null input. Tuttavia, se l'input può essere null, il valore restituito può anche essere null.However, if the input could be null, then return value could also be null. È possibile modificare la firma con il codice seguente:You could change the signature to the following code:

string? GetTopLevelDomainFromFullUrl(string? url);

Che funziona, ma spesso impone ai chiamanti di implementare controlli aggiuntivi null .That also works, but will often force callers to implement extra null checks. Il contratto è che il valore restituito null è solo quando l'argomento di input url è null .The contract is that the return value would be null only when the input argument url is null. Per esprimere il contratto, è necessario annotare questo metodo come illustrato nel codice seguente:To express that contract, you would annotate this method as shown in the following code:

[return: NotNullIfNotNull("url")]
string? GetTopLevelDomainFromFullUrl(string? url);

Il valore restituito e l'argomento sono entrambi annotati con l'oggetto ? che indica che può essere null .The return value and the argument have both been annotated with the ? indicating that either could be null. L'attributo chiarisce ulteriormente che il valore restituito non sarà null quando l' url argomento non è null .The attribute further clarifies that the return value won't be null when the url argument isn't null.

È possibile specificare le postcondizioni condizionali usando questi attributi:You specify conditional postconditions using these attributes:

  • MaybeNullWhen: un argomento di input che non ammette i valori null può essere null quando il metodo restituisce il bool valore specificato.MaybeNullWhen: A non-nullable input argument may be null when the method returns the specified bool value.
  • NotNullWhen: un argomento di input nullable non sarà null quando il metodo restituisce il bool valore specificato.NotNullWhen: A nullable input argument won't be null when the method returns the specified bool value.
  • NotNullIfNotNull: un valore restituito non è null se l'argomento di input per il parametro specificato non è null.NotNullIfNotNull: A return value isn't null if the input argument for the specified parameter isn't null.

Metodi helper del costruttore: MemberNotNull e MemberNotNullWhenConstructor helper methods: MemberNotNull and MemberNotNullWhen

Questi attributi specificano l'intento quando è stato eseguito il refactoring del codice comune dai costruttori ai metodi helper.These attributes specify your intent when you've refactored common code from constructors into helper methods. Il compilatore C# analizza i costruttori e gli inizializzatori di campo per assicurarsi che tutti i campi di riferimento che non ammettono i valori null siano stati inizializzati prima che ogni costruttore venga restituito.The C# compiler analyzes constructors and field initializers to make sure that all non-nullable reference fields have been initialized before each constructor returns. Tuttavia, il compilatore C# non tiene traccia delle assegnazioni dei campi tramite tutti i metodi helper.However, the C# compiler doesn't track field assignments through all helper methods. Il compilatore genera un avviso CS8618 quando i campi non vengono inizializzati direttamente nel costruttore, ma piuttosto in un metodo helper.The compiler issues warning CS8618 when fields aren't initialized directly in the constructor, but rather in a helper method. Si aggiunge MemberNotNullAttribute a una dichiarazione di metodo e si specificano i campi inizializzati su un valore non null nel metodo.You add the MemberNotNullAttribute to a method declaration and specify the fields that are initialized to a non-null value in the method. Ad esempio, si consideri l'esempio seguente:For example, consider the following example:

public class Container
{
    private string _uniqueIdentifier; // must be initialized.
    private string? _optionalMessage;

    public Container()
    {
        Helper();
    }

    public Container(string message)
    {
        Helper();
        _optionalMessage = message;
    }

    [MemberNotNull(nameof(_uniqueIdentifier))]
    private void Helper()
    {
        _uniqueIdentifier = DateTime.Now.Ticks.ToString();
    }
}

È possibile specificare più nomi di campo come argomenti per il MemberNotNull costruttore dell'attributo.You can specify multiple field names as arguments to the MemberNotNull attribute constructor.

MemberNotNullWhenAttributeHa un bool argomento.The MemberNotNullWhenAttribute has a bool argument. Usare MemberNotNullWhen nelle situazioni in cui il metodo helper restituisce un valore bool che indica se i campi inizializzati dal metodo helper.You use MemberNotNullWhen in situations where your helper method returns a bool indicating whether your helper method initialized fields.

Verificare il codice non eseguibileVerify unreachable code

Alcuni metodi, in genere helper di eccezioni o altri metodi di utilità, vengono sempre terminati generando un'eccezione.Some methods, typically exception helpers or other utility methods, always exit by throwing an exception. In alternativa, un helper può generare un'eccezione in base al valore di un argomento booleano.Or, a helper may throw an exception based on the value of a Boolean argument.

Nel primo caso, è possibile aggiungere l' DoesNotReturn attributo alla dichiarazione del metodo.In the first case, you can add the DoesNotReturn attribute to the method declaration. Il compilatore consente di in tre modi.The compiler helps you in three ways. Prima di tutto, il compilatore genera un avviso se è presente un percorso in cui il metodo può uscire senza generare un'eccezione.First, the compiler issues a warning if there's a path where the method can exit without throwing an exception. In secondo luogo, il compilatore contrassegna il codice dopo una chiamata a tale metodo come non raggiungibile, fino a quando non catch viene trovata una clausola appropriata.Second, the compiler marks any code after a call to that method as unreachable, until an appropriate catch clause is found. In terzo luogo, il codice non eseguibile non influirà sugli stati null.Third, the unreachable code won't affect any null states. Si consideri il metodo seguente:Consider this method:

[DoesNotReturn]
private void FailFast()
{
    throw new InvalidOperationException();
}

public void SetState(object containedField)
{
    if (!isInitialized)
    {
        FailFast();
    }

    // unreachable code:
    _field = containedField;
}

Nel secondo caso, si aggiunge l' DoesNotReturnIf attributo a un parametro booleano del metodo.In the second case, you add the DoesNotReturnIf attribute to a Boolean parameter of the method. È possibile modificare l'esempio precedente nel modo seguente:You can modify the previous example as follows:

private void FailFast([DoesNotReturnIf(false)] bool isValid)
{
    if (!isValid)
    {
        throw new InvalidOperationException();
    }
}

public void SetState(object containedField)
{
    FailFast(isInitialized);

    // unreachable code when "isInitialized" is false:
    _field = containedField;
}

RiepilogoSummary

Importante

La documentazione ufficiale tiene traccia della versione più recente di C#.The official documentation tracks the latest C# version. È in corso la scrittura per C# 9,0.We are currently writing for C# 9.0. A seconda della versione di C# utilizzata, potrebbero non essere disponibili diverse funzionalità.Depending on the version of C# you're using, various features may not be available. La versione C# predefinita per il progetto è basata sul Framework di destinazione.The default C# version for your project is based on the target framework. Per altre informazioni, vedere impostazioni predefinite per il controllo delle versioni del linguaggio C#.For more information, see C# language versioning defaults.

L'aggiunta di tipi di riferimento Nullable fornisce un vocabolario iniziale per descrivere le aspettative delle API per le variabili che potrebbero essere null .Adding nullable reference types provides an initial vocabulary to describe your APIs expectations for variables that could be null. Gli attributi forniscono un vocabolario più completo per descrivere lo stato null delle variabili come precondizioni e postcondizioni.The attributes provide a richer vocabulary to describe the null state of variables as preconditions and postconditions. Questi attributi descrivono in modo più chiaro le aspettative e offrono un'esperienza migliore per gli sviluppatori che usano le API.These attributes more clearly describe your expectations and provide a better experience for the developers using your APIs.

Quando si aggiornano le librerie per un contesto Nullable, aggiungere questi attributi per guidare gli utenti delle API all'uso corretto.As you update libraries for a nullable context, add these attributes to guide users of your APIs to the correct usage. Questi attributi consentono di descrivere completamente lo stato null degli argomenti di input e dei valori restituiti:These attributes help you fully describe the null-state of input arguments and return values:

  • AllowNull: un argomento di input che non ammette i valori null può essere null.AllowNull: A non-nullable input argument may be null.
  • DisallowNull: un argomento di input nullable non deve mai essere null.DisallowNull: A nullable input argument should never be null.
  • MaybeNull: un valore restituito non nullable può essere null.MaybeNull: A non-nullable return value may be null.
  • NotNull: un valore restituito nullable non sarà mai null.NotNull: A nullable return value will never be null.
  • MaybeNullWhen: un argomento di input che non ammette i valori null può essere null quando il metodo restituisce il bool valore specificato.MaybeNullWhen: A non-nullable input argument may be null when the method returns the specified bool value.
  • NotNullWhen: un argomento di input nullable non sarà null quando il metodo restituisce il bool valore specificato.NotNullWhen: A nullable input argument won't be null when the method returns the specified bool value.
  • NotNullIfNotNull: un valore restituito non è null se l'argomento di input per il parametro specificato non è null.NotNullIfNotNull: A return value isn't null if the input argument for the specified parameter isn't null.
  • DoesNotReturn: un metodo non restituisce mai.DoesNotReturn: A method never returns. In altre parole, genera sempre un'eccezione.In other words, it always throws an exception.
  • DoesNotReturnIf: questo metodo non restituisce mai se il bool valore specificato per il parametro associato è.DoesNotReturnIf: This method never returns if the associated bool parameter has the specified value.