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.
Suggerimento
Questo articolo fa parte della sezione Nozioni fondamentali per gli sviluppatori che conoscono almeno un linguaggio di programmazione e stanno imparando C#. Se non si ha familiarità con la programmazione, iniziare prima con le esercitazioni introduttive . Per informazioni di riferimento sull'operatore completo, vedere Operatori di accesso ai membri e operatori null-coalescing nel riferimento al linguaggio.
C# offre diversi operatori che rendono conciso il codice null-safe. Anziché annidare if (x != null) le guardie in tutto il codice, questi operatori consentono di esprimere in una singola espressione l'accesso sicuro ai valori nulli, i valori di fallback e i test di null.
Questo articolo illustra ?. e ?[] per l'accesso condizionale null, ?? per l'operatore di coalescenza null, ??= per l'assegnazione con coalescenza null e is null/is not null per il confronto di pattern null.
Accesso ai membri condizionali Null ?.
L'operatore ?. accede a un membro solo quando l'oggetto è diverso da Null. Quando l'oggetto è null, l'intera espressione restituisce null invece di generare un NullReferenceExceptionoggetto :
string? name = null;
// Without ?., accessing a member on null throws NullReferenceException:
// int len = name.Length; // throws if name is null
// ?. returns null instead of throwing:
int? len = name?.Length;
Console.WriteLine(len.HasValue); // False
name = "C#";
Console.WriteLine(name?.Length); // 2
L'operatore ?.: quando l'operando sinistro è , tutto ciò che è a destra viene ignorato. Nessuna chiamata al metodo viene eseguita e non si verificano effetti collaterali.
È possibile concatenare più ?. operatori in una singola espressione. La catena si ferma al primo null incontrato.
string? input = null;
// Chain ?. across multiple method calls — short-circuits at the first null:
string? upper = input?.Trim()?.ToUpperInvariant();
Console.WriteLine(upper ?? "(none)"); // (none)
input = " hello ";
Console.WriteLine(input?.Trim()?.ToUpperInvariant()); // HELLO
Accesso dell'indicizzatore condizionale Null ?[]
L'operatore ?[] applica lo stesso comportamento a corto circuito all'indicizzatore e all'accesso alla matrice. Usarlo quando la raccolta stessa potrebbe essere null:
string[]? tags = null;
// ?[] accesses an element only when the collection is non-null
string? first = tags?[0];
Console.WriteLine(first ?? "(none)"); // (none)
tags = ["csharp", "dotnet", "nullable"];
Console.WriteLine(tags?[0]); // csharp
Concatenare operatori null-condizionali
Collegare più ?. operatori per attraversare un percorso di riferimenti potenzialmente null. Cortocircuito della catena al primo null:
var order = new Order("ORD-001", null);
// Each ?. short-circuits when null: Customer is null, so Address and City are never accessed
string? city = order.Customer?.Address?.City;
Console.WriteLine(city ?? "(no city)"); // (no city)
var fullOrder = new Order("ORD-002",
new Customer("Alice", new Address("123 Main St", "Springfield", "IL")));
Console.WriteLine(fullOrder.Customer?.Address?.City); // Springfield
Quando Customer è null, né Address né City viene valutato. L'intera espressione restituisce null.
Invocazione di delegati thread-safe
?. fornisce un modo pulito e thread-safe per richiamare un delegato o generare un evento. L'espressione del delegato viene valutata una sola volta, quindi non esiste alcuna finestra per un altro thread per annullare la sottoscrizione tra il controllo Null e la chiamata:
EventHandler? clicked = null;
// No subscribers — ?.Invoke does nothing instead of throwing NullReferenceException
clicked?.Invoke(null, EventArgs.Empty);
clicked += (_, _) => Console.WriteLine("Button clicked!");
// With a subscriber — ?.Invoke calls the handler
clicked?.Invoke(null, EventArgs.Empty);
// Output: Button clicked!
Questo modello sostituisce il linguaggio precedente if (clicked != null) clicked(...) .
Operatore di coalescenza dei null ??
L'operatore ?? restituisce l'operando a sinistra quando è diverso da Null e l'operando di destra quando la sinistra è null. Usarlo per specificare un valore predefinito:
string? username = null;
// ?? returns the right-hand value when the left-hand is null
string display = username ?? "Guest";
Console.WriteLine(display); // Guest
username = "alice";
display = username ?? "Guest";
Console.WriteLine(display); // alice
?? è associativo a destra, quindi a ?? b ?? c si valuta come a ?? (b ?? c). Il primo valore non Null prevale. Un modello comune consiste nel concatenare ?. con ??: usare ?. per attraversare in modo sicuro una catena null-possibile, quindi ?? sostituire un valore predefinito se la catena ha restituito null. Per un esempio completo, vedere Combinare operatori Null.
Assegnazione null-coalescing ??=
L'operatore ??= assegna il valore di destra a una variabile solo quando la variabile è null. Utilizzalo per l'inizializzazione pigra:
List<string>? cache = null;
// ??= assigns only when the variable is null
cache ??= LoadData();
Console.WriteLine(cache.Count); // 3
// cache is already non-null, so LoadData() isn't called again
cache ??= LoadData();
Console.WriteLine(cache.Count); // 3
static List<string> LoadData() => ["alpha", "beta", "gamma"];
L'espressione a destra viene valutata solo quando la variabile è null. Quando la variabile ha già un valore, il lato destro non viene valutato affatto.
Assegnazione null-conditionale (C# 14)
A partire da C# 14, è possibile usare ?. e ?[] come destinazioni di assegnazione. L'assegnazione viene eseguita solo quando l'oggetto a sinistra non è nullo.
AppConfig? config = new AppConfig();
// Assigns only when config is non-null (C# 14)
config?.Theme = "dark";
Console.WriteLine(config?.Theme); // dark
AppConfig? missing = null;
missing?.Theme = "light"; // no-op: missing is null
Console.WriteLine(missing?.Theme ?? "(no config)"); // (no config)
Il lato destro viene valutato solo quando il lato sinistro è noto per essere non nullo.
Corrispondenza di modelli Null: is null e is not null
I is null modelli e is not null testano se un'espressione è null:
string? input = null;
// is null is the preferred test — unaffected by operator overloading
if (input is null)
{
Console.WriteLine("No input provided.");
}
// == null also works, but a custom == operator can change its behavior
if (input == null)
{
Console.WriteLine("Still no input.");
}
Preferire is null rispetto a == null per i controlli null. L'operatore == può essere sottoposto a overload, ovvero x == null può restituire true anche quando x non null è se il tipo definisce un operatore di uguaglianza personalizzato. Il is null modello verifica sempre il riferimento null effettivo, indipendentemente dagli operatori sovraccaricati.
string? value = "hello";
if (value is not null)
{
Console.WriteLine(value.ToUpper()); // HELLO
}
Combinare operatori Null
In pratica, spesso si combinano diversi di questi operatori. Un'espressione può attraversare in modo sicuro un grafico di oggetti profondi, applicare un fallback e quindi proteggere il risultato:
Order? order = GetPendingOrder();
// Chain ?. for safe traversal, ?? for a fallback, is null for a clear guard
string city = order?.Customer?.Address?.City ?? "unknown";
if (order is null)
{
Console.WriteLine("No pending order.");
}
else
{
Console.WriteLine($"Shipping to: {city}");
}
// Output: No pending order.
Operatore Null-forgiving !
L'operatore ! postfix sopprime gli avvisi nullable. Aggiungere ! per indicare al compilatore "questa espressione non è sicuramente null". L'operatore non ha alcun effetto in fase di esecuzione. Influisce solo sull'analisi dello stato Null del compilatore.
string? name = FindUser("alice");
// Use ! only when you have information the compiler doesn't.
// FindUser guarantees a non-null result for known usernames.
int length = name!.Length;
Console.WriteLine(length); // 5
Usa ! con moderazione e solo quando si dispone di informazioni che il compilatore non ha. Gli esempi includono test che passano intenzionalmente null per convalidare la logica di controllo degli argomenti o chiamare un metodo il cui contratto garantisce un ritorno non nullo per un input noto. L'utilizzo eccessivo di ! sconfigge lo scopo dei tipi di riferimento nullable. Per una spiegazione completa, vedere Tipi di riferimento Nullable.