Condividi tramite


Tipi valore nullable (Riferimenti per C#)

Un tipo valore che ammette i valori NullT? rappresenta tutti i valori del tipo valoreT sottostante e un valore null aggiuntivo. Ad esempio, è possibile assegnare uno dei tre valori seguenti a una variabile bool?: true, falseo null. Un tipo di T valore sottostante non può essere un tipo valore nullable.

Il riferimento al linguaggio C# documenta la versione rilasciata più di recente del linguaggio C#. Contiene anche la documentazione iniziale per le funzionalità nelle anteprime pubbliche per la versione futura del linguaggio.

La documentazione identifica tutte le funzionalità introdotte nelle ultime tre versioni della lingua o nelle anteprime pubbliche correnti.

Suggerimento

Per trovare quando una funzionalità è stata introdotta per la prima volta in C#, vedere l'articolo sulla cronologia delle versioni del linguaggio C#.

Qualsiasi tipo di valore nullable è un'istanza della struttura generica System.Nullable<T>. È possibile fare riferimento a un tipo valore nullable con un tipo T sottostante in uno dei formati intercambiabili seguenti: Nullable<T> o T?.

In genere, usare un tipo valore nullable quando è necessario rappresentare il valore non definito di un tipo valore sottostante. Ad esempio, una variabile booleana, o bool, può essere solo true o false. Tuttavia, in alcune applicazioni un valore di variabile può essere indefinito o mancante. Ad esempio, un campo di database può contenere true o oppure falsepotrebbe non contenere alcun valore, NULLovvero . È possibile usare il tipo bool? in tale scenario.

Dichiarazione e assegnazione

Poiché un tipo valore è convertibile in modo implicito nel tipo di valore nullable corrispondente, è possibile assegnare un valore a una variabile di un tipo valore nullable come si fa per il tipo di valore sottostante. È anche possibile assegnare il valore null. Ad esempio:

double? pi = 3.14;
char? letter = 'a';

int m2 = 10;
int? m = m2;

bool? flag = null;

// An array of a nullable value type:
int?[] arr = new int?[10];

Il valore predefinito di un tipo valore nullable rappresenta null. Si tratta di un'istanza la cui Nullable<T>.HasValue proprietà restituisce false.

Esame di un'istanza di un tipo valore nullable

Per controllare un'istanza di un tipo valore nullable per null e ottenere un valore di un tipo sottostante, usare l'operatoreis con un criterio di tipo:

int? a = 42;
if (a is int valueOfA)
{
    Console.WriteLine($"a is {valueOfA}");
}
else
{
    Console.WriteLine("a does not have a value");
}
// Output:
// a is 42

È sempre possibile usare le proprietà di sola lettura seguenti per controllare e ottenere un valore di una variabile di tipo valore nullable:

Nell'esempio seguente viene utilizzata la HasValue proprietà per verificare se la variabile contiene un valore prima di visualizzarlo:

int? b = 10;
if (b.HasValue)
{
    Console.WriteLine($"b is {b.Value}");
}
else
{
    Console.WriteLine("b does not have a value");
}
// Output:
// b is 10

È anche possibile confrontare una variabile di un tipo valore nullable con null anziché usare la proprietà HasValue, come illustrato nell'esempio seguente:

int? c = 7;
if (c != null)
{
    Console.WriteLine($"c is {c.Value}");
}
else
{
    Console.WriteLine("c does not have a value");
}
// Output:
// c is 7

Conversione da un tipo di valore nullable a un tipo sottostante

Se si vuole assegnare un valore di tipo valore nullable a una variabile di tipo valore non nullable, potrebbe essere necessario specificare il valore da assegnare al posto di null. Usare l'operatore ??null-coalescing per eseguire questa operazione. È anche possibile usare il Nullable<T>.GetValueOrDefault(T) metodo per lo stesso scopo:

int? a = 28;
int b = a ?? -1;
Console.WriteLine($"b is {b}");  // output: b is 28

int? c = null;
int d = c ?? -1;
Console.WriteLine($"d is {d}");  // output: d is -1

Se si vuole usare il valore predefinito del tipo di valore sottostante al posto di null, usare il metodo Nullable<T>.GetValueOrDefault().

È anche possibile eseguire il cast esplicito di un tipo valore nullable a un tipo non nullable, come illustrato nell'esempio seguente:

int? n = null;

//int m1 = n;    // Doesn't compile
int n2 = (int)n; // Compiles, but throws an exception if n is null

Se in fase di esecuzione il valore di un tipo nullable è null, il cast esplicito genera un'eccezione InvalidOperationException.

Un tipo valore non nullable T viene convertito in modo implicito nel tipo di valore nullable corrispondente T?.

Operatori lifted

Un tipo valore T? nullable supporta gli operatori unari e binari predefiniti o qualsiasi operatore di overload supportato da un tipo valore T . Questi operatori, noti anche come operatori lifted, restituiscono null se uno o entrambi gli operandi sono null. In caso contrario, l'operatore utilizza i valori contenuti dei relativi operandi per calcolare il risultato. Ad esempio:

int? a = 10;
int? b = null;
int? c = 10;

a++;        // a is 11
a = a * c;  // a is 110
a = a + b;  // a is null

Nota

Per il tipo bool?, gli operatori predefiniti & e | non si attengono alle regole descritte in questa sezione: il risultato di una valutazione degli operatori può essere non Null, anche se uno degli operandi è null. Per altre informazioni, vedere la sezione Operatori logici booleani nullable dell'articolo Operatori logici booleani.

Per gli operatori <di confronto, >, <=e >=, se uno o entrambi gli operandi sono null, il risultato è false. In caso contrario, vengono confrontati i valori contenuti degli operandi. Non presupporre che poiché un particolare confronto ( ad esempio , <=) restituisce false, il confronto opposto (>) restituisce true. L'esempio seguente mostra che 10

  • non è né maggiore o uguale a null
  • né minore di null
int? a = 10;
Console.WriteLine($"{a} >= null is {a >= null}");
Console.WriteLine($"{a} < null is {a < null}");
Console.WriteLine($"{a} == null is {a == null}");
// Output:
// 10 >= null is False
// 10 < null is False
// 10 == null is False

int? b = null;
int? c = null;
Console.WriteLine($"null >= null is {b >= c}");
Console.WriteLine($"null == null is {b == c}");
// Output:
// null >= null is False
// null == null is True

Per l'operatore== di uguaglianza, se entrambi gli operandi sono null, il risultato è true. Se solo uno degli operandi è null, il risultato è false. In caso contrario, vengono confrontati i valori contenuti degli operandi.

Per l'operatore !=di disuguaglianza, se entrambi gli operandi sono null, il risultato è false. Se solo uno degli operandi è null, il risultato è true. In caso contrario, vengono confrontati i valori contenuti degli operandi.

Se esiste una conversione definita dall'utente tra due tipi valore, la stessa conversione può essere usata anche tra i tipi di valore nullable corrispondenti.

Boxing e unboxing

Quando si esegue una casella di un'istanza di un tipo T?valore nullable, si applicano le regole seguenti:

  • Se HasValue restituisce false, l'operazione boxing restituisce il riferimento Null.
  • Se HasValue restituisce true, l'operazione boxing riquadri il valore corrispondente del tipo di Tvalore sottostante, non l'istanza di Nullable<T>.

È possibile eseguire la conversione unboxing del tipo valore T sottoposto a boxing nel tipo valore nullable T? corrispondente, come illustrato nell'esempio seguente:

int a = 41;
object aBoxed = a;
int? aNullable = (int?)aBoxed;
Console.WriteLine($"Value of aNullable: {aNullable}");

object aNullableBoxed = aNullable;
if (aNullableBoxed is int valueOfA)
{
    Console.WriteLine($"aNullableBoxed is boxed int: {valueOfA}");
}
// Output:
// Value of aNullable: 41
// aNullableBoxed is boxed int: 41

Procedura: Identificare un tipo valore nullable

Nell'esempio seguente viene illustrato come determinare se un'istanza System.Type rappresenta un tipo valore nullable costruito, ovvero il tipo System.Nullable<T> con un parametro di tipo specificato T:

Console.WriteLine($"int? is {(IsNullable(typeof(int?)) ? "nullable" : "non nullable")} value type");
Console.WriteLine($"int is {(IsNullable(typeof(int)) ? "nullable" : "non-nullable")} value type");

bool IsNullable(Type type) => Nullable.GetUnderlyingType(type) != null;

// Output:
// int? is nullable value type
// int is non-nullable value type

Come illustrato nell'esempio, si usa l'operatore typeof per creare un'istanza System.Type.

Se si vuole determinare se un'istanza è di un tipo valore nullable, non usare il Object.GetType metodo per ottenere un'istanza Type da testare usando il codice precedente. Quando si chiama il metodo Object.GetType in un'istanza di un tipo nullable, viene eseguita la conversione boxing dell'istanza a Object. Poiché la conversione boxing di un'istanza non Null di un tipo valore nullable equivale al boxing di un valore del tipo sottostante, GetType restituisce un'istanza Type che rappresenta il tipo sottostante di un tipo valore nullable:

int? a = 17;
Type typeOfA = a.GetType();
Console.WriteLine(typeOfA.FullName);
// Output:
// System.Int32

Inoltre, non usare l’operatore is per determinare se un'istanza è di un tipo valore nullable. Come illustrato nell'esempio seguente, non è possibile distinguere i tipi di un'istanza di tipo valore nullable e l'istanza del tipo sottostante usando l'operatore is :

int? a = 14;
if (a is int)
{
    Console.WriteLine("int? instance is compatible with int");
}

int b = 17;
if (b is int?)
{
    Console.WriteLine("int instance is compatible with int?");
}
// Output:
// int? instance is compatible with int
// int instance is compatible with int?

Usare invece il Nullable.GetUnderlyingType metodo del primo esempio e l'operatore typeof per verificare se un'istanza è di un tipo valore nullable.

Nota

I metodi descritti in questa sezione non si applicano ai tipi riferimento nullable.

Specifiche del linguaggio C#

Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#:

Vedi anche