Tipi di valore Nullable (riferimenti per C#)Nullable value types (C# reference)

Un tipo di valore Nullable T? rappresenta tutti i valori del tipo di valore sottostante T e un valore null aggiuntivo.A nullable value type T? represents all values of its underlying value type T and an additional null value. È ad esempio possibile assegnare a una variabile uno dei tre valori seguenti bool? : true , false o null .For example, you can assign any of the following three values to a bool? variable: true, false, or null. Un tipo di valore sottostante T non può essere un tipo di valore Nullable.An underlying value type T cannot be a nullable value type itself.

Nota

C# 8,0 introduce la funzionalità dei tipi di riferimento Nullable.C# 8.0 introduces the nullable reference types feature. Per altre informazioni, vedere tipi di riferimento Nullable.For more information, see Nullable reference types. I tipi di valore nullable sono disponibili a partire da C# 2.The nullable value types are available beginning with C# 2.

Qualsiasi tipo di valore Nullable è un'istanza della struttura generica System.Nullable<T> .Any nullable value type is an instance of the generic System.Nullable<T> structure. È possibile fare riferimento a un tipo di valore nullable con un tipo sottostante T in uno qualsiasi dei seguenti formati intercambiabili: Nullable<T> o T? .You can refer to a nullable value type with an underlying type T in any of the following interchangeable forms: Nullable<T> or T?.

Si usa in genere un tipo di valore nullable quando è necessario rappresentare il valore non definito di un tipo di valore sottostante.You typically use a nullable value type when you need to represent the undefined value of an underlying value type. Una variabile booleana o, ad esempio, bool può essere solo true o false .For example, a Boolean, or bool, variable can only be either true or false. Tuttavia, in alcune applicazioni un valore di variabile può essere non definito o mancante.However, in some applications a variable value can be undefined or missing. Ad esempio, un campo di database può contenere o oppure non true false può contenere alcun valore, ovvero NULL .For example, a database field may contain true or false, or it may contain no value at all, that is, NULL. È possibile utilizzare il bool? tipo in questo scenario.You can use the bool? type in that scenario.

Dichiarazione e assegnazioneDeclaration and assignment

Poiché un tipo valore è convertibile in modo implicito nel tipo di valore nullable corrispondente, è possibile assegnare un valore a una variabile di un tipo di valore nullable come per il tipo di valore sottostante.As a value type is implicitly convertible to the corresponding nullable value type, you can assign a value to a variable of a nullable value type as you would do that for its underlying value type. È anche possibile assegnare il null valore.You can also assign the null value. Ad esempio:For example:

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 di valore Nullable rappresenta null , ovvero un'istanza la cui Nullable<T>.HasValue proprietà restituisce false .The default value of a nullable value type represents null, that is, it's an instance whose Nullable<T>.HasValue property returns false.

Esame di un'istanza di un tipo di valore NullableExamination of an instance of a nullable value type

A partire da C# 7,0, è possibile usare l' is operatore con un modello di tipo per esaminare un'istanza di un tipo di valore Nullable per null e recuperare un valore di un tipo sottostante:Beginning with C# 7.0, you can use the is operator with a type pattern to both examine an instance of a nullable value type for null and retrieve a value of an underlying type:

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

Per esaminare e ottenere un valore di una variabile di tipo valore Nullable, è sempre possibile usare le proprietà di sola lettura seguenti:You always can use the following read-only properties to examine and get a value of a nullable value type variable:

Nell'esempio seguente viene usata la HasValue proprietà per verificare se la variabile contiene un valore prima di visualizzarlo:The following example uses the HasValue property to test whether the variable contains a value before displaying it:

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 di valore nullable con null invece di usare la HasValue proprietà, come illustrato nell'esempio seguente:You can also compare a variable of a nullable value type with null instead of using the HasValue property, as the following example shows:

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 sottostanteConversion from a nullable value type to an underlying type

Se si desidera assegnare un valore di un tipo di valore Nullable a una variabile di tipo valore non nullable, potrebbe essere necessario specificare il valore da assegnare al posto di null .If you want to assign a value of a nullable value type to a non-nullable value type variable, you might need to specify the value to be assigned in place of null. Per eseguire questa operazione, usare l' ?? operatore di Unione null (è anche possibile usare il Nullable<T>.GetValueOrDefault(T) metodo per lo stesso scopo):Use the null-coalescing operator ?? to do that (you can also use the Nullable<T>.GetValueOrDefault(T) method for the same purpose):

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 desidera utilizzare il valore predefinito del tipo di valore sottostante al posto di null , utilizzare il Nullable<T>.GetValueOrDefault() metodo.If you want to use the default value of the underlying value type in place of null, use the Nullable<T>.GetValueOrDefault() method.

È anche possibile eseguire il cast esplicito di un tipo di valore Nullable a un tipo non nullable, come illustrato nell'esempio seguente:You can also explicitly cast a nullable value type to a non-nullable type, as the following example shows:

int? n = null;

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

In fase di esecuzione, se il valore di un tipo di valore Nullable è null , il cast esplicito genera un'eccezione InvalidOperationException .At run time, if the value of a nullable value type is null, the explicit cast throws an InvalidOperationException.

Un tipo valore non Nullable T è convertibile in modo implicito nel tipo di valore nullable corrispondente T? .A non-nullable value type T is implicitly convertible to the corresponding nullable value type T?.

Operatori rimossiLifted operators

Gli operatori unari e binari predefiniti o gli operatori di overload supportati da un tipo di valore T sono supportati anche dal tipo di valore nullable corrispondente T? .The predefined unary and binary operators or any overloaded operators that are supported by a value type T are also supported by the corresponding nullable value type T?. Questi operatori, noti anche come operatori Lift, producono null se uno o entrambi gli operandi sono null ; in caso contrario, l'operatore usa i valori contenuti degli operandi per calcolare il risultato.These operators, also known as lifted operators, produce null if one or both operands are null; otherwise, the operator uses the contained values of its operands to calculate the result. Ad esempio:For example:

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 bool? tipo, gli operatori predefiniti & e | non seguono le regole descritte in questa sezione: il risultato di una valutazione dell'operatore può essere diverso da null anche se uno degli operandi è null .For the bool? type, the predefined & and | operators don't follow the rules described in this section: the result of an operator evaluation can be non-null even if one of the operands is null. Per altre informazioni, vedere la sezione Operatori logici booleani nullable dell'articolo Operatori logici booleani.For more information, see the Nullable Boolean logical operators section of the Boolean logical operators article.

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.For the comparison operators <, >, <=, and >=, if one or both operands are null, the result is false; otherwise, the contained values of operands are compared. Non presupporre che poiché un particolare confronto (ad esempio, <=) restituisce false, il confronto opposto (>) restituisce true.Do not assume that because a particular comparison (for example, <=) returns false, the opposite comparison (>) returns true. L'esempio seguente mostra che 10The following example shows that 10 is

  • non è maggiore o uguale a nullneither greater than or equal to null
  • né minore di nullnor less than 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.For the equality operator ==, if both operands are null, the result is true, if only one of the operands is null, the result is false; otherwise, the contained values of operands are compared.

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.For the inequality operator !=, if both operands are null, the result is false, if only one of the operands is null, the result is true; otherwise, the contained values of operands are compared.

Se esiste una conversione definita dall'utente tra due tipi di valore, è possibile usare la stessa conversione anche tra i tipi di valore nullable corrispondenti.If there exists a user-defined conversion between two value types, the same conversion can also be used between the corresponding nullable value types.

Boxing e unboxingBoxing and unboxing

Un'istanza di un tipo di valore Nullable T? è boxed come indicato di seguito:An instance of a nullable value type T? is boxed as follows:

  • Se HasValue restituisce false, viene prodotto il riferimento Null.If HasValue returns false, the null reference is produced.
  • Se HasValue restituisce true , il valore corrispondente del tipo di valore sottostante T è boxed, non l'istanza di Nullable<T> .If HasValue returns true, the corresponding value of the underlying value type T is boxed, not the instance of Nullable<T>.

È possibile eseguire l'unboxing di un valore boxed di un tipo di valore nel T tipo di valore nullable corrispondente T? , come illustrato nell'esempio seguente:You can unbox a boxed value of a value type T to the corresponding nullable value type T?, as the following example shows:

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

Come identificare un tipo di valore NullableHow to identify a nullable value type

Nell'esempio seguente viene illustrato come determinare se un' System.Type istanza rappresenta un tipo di valore Nullable costruito, ovvero il System.Nullable<T> tipo con un parametro di tipo specificato T :The following example shows how to determine whether a System.Type instance represents a constructed nullable value type, that is, the System.Nullable<T> type with a specified type parameter 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' System.Type istanza.As the example shows, you use the typeof operator to create a System.Type instance.

Se si desidera determinare se un'istanza è di un tipo di valore Nullable, non utilizzare il Object.GetType metodo per ottenere un' Type istanza di da testare con il codice precedente.If you want to determine whether an instance is of a nullable value type, don't use the Object.GetType method to get a Type instance to be tested with the preceding code. Quando si chiama il Object.GetType metodo su un'istanza di un tipo di valore Nullable, l'istanza viene sottoposta a Boxing a Object .When you call the Object.GetType method on an instance of a nullable value type, the instance is boxed to Object. Poiché la conversione boxing di un'istanza non null di un tipo di valore Nullable equivale alla conversione boxing di un valore del tipo sottostante, GetType restituisce un' Type istanza di che rappresenta il tipo sottostante di un tipo di valore Nullable:As boxing of a non-null instance of a nullable value type is equivalent to boxing of a value of the underlying type, GetType returns a Type instance that represents the underlying type of a nullable value type:

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 è un tipo di valore Nullable.Also, don't use the is operator to determine whether an instance is of a nullable value type. Come illustrato nell'esempio seguente, non è possibile distinguere i tipi di un'istanza del tipo di valore nullable e l'istanza del tipo sottostante con l' is operatore:As the following example shows, you cannot distinguish types of a nullable value type instance and its underlying type instance with the is operator:

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?

È possibile utilizzare il codice presentato nell'esempio seguente per determinare se un'istanza è un tipo di valore Nullable:You can use the code presented in the following example to determine whether an instance is of a nullable value type:

int? a = 14;
Console.WriteLine(IsOfNullableType(a));  // output: True

int b = 17;
Console.WriteLine(IsOfNullableType(b));  // output: False

bool IsOfNullableType<T>(T o)
{
    var type = typeof(T);
    return Nullable.GetUnderlyingType(type) != null;
}

Nota

I metodi descritti in questa sezione non sono applicabili in caso di tipi di riferimento Nullable.The methods described in this section are not applicable in the case of nullable reference types.

Specifiche del linguaggio C#C# language specification

Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#:For more information, see the following sections of the C# language specification:

Vedi ancheSee also