Condividi tramite


Utilizzo dei tipi nullable (Guida per programmatori C#)

I tipi nullable possono rappresentare tutti i valori di un tipo sottostante e un valore null aggiuntivo. Vengono dichiarati in uno dei seguenti modi:

System.Nullable<T> variable

In alternativa

T? variable

T è il tipo sottostante del tipo nullable. T può essere qualsiasi tipo di valore, compreso struct, ma non può essere un tipo di riferimento.

Per un esempio relativo ai casi di utilizzo di un tipo nullable, si consideri che una variabile booleana ordinaria può avere due valori: true e false. Non esiste alcun valore che significa "non definito". In numerose applicazioni di programmazione, in particolare nelle interazioni di database, possono essere presenti variabili con uno stato non definito. Un campo di un database, ad esempio, può contenere i valori true o false, ma può anche non contenere alcun valore. Analogamente, i tipi di riferimento possono essere impostati su null per indicare che non sono inizializzati.

Questa differenza può comportare un aumento del lavoro di programmazione poiché richiede l'utilizzo di ulteriori variabili per archiviare le informazioni sullo stato, l'utilizzo di valori speciali e così via. Mediante il modificatore dei tipi nullable, in C# è possibile creare variabili di tipo di valore che indicano un valore non definito.

Esempi di tipi nullable

È possibile utilizzare qualsiasi tipo di valore come base per un tipo nullable. Di seguito è riportato un esempio.

int? i = 10;
double? d1 = 3.14;
bool? flag = null;
char? letter = 'a';
int?[] arr = new int?[10];

Membri dei tipi nullable

Ogni istanza di un tipo nullable dispone di due proprietà pubbliche in sola lettura:

  • HasValue

    HasValue è di tipo bool. È impostata su true se la variabile contiene un valore non null.

  • Value

    Value è dello stesso tipo del tipo sottostante. Se HasValue è impostata su true, Value conterrà un valore significativo. Se HasValue è impostata su false, l'accesso a Value genererà un'eccezione InvalidOperationException.

In questo esempio viene utilizzato il membro HasValue per verificare se la variabile contiene un valore prima di tentare di visualizzarlo.

int? x = 10;
if (x.HasValue)
{
    System.Console.WriteLine(x.Value);
}
else
{
    System.Console.WriteLine("Undefined");
}

È anche possibile eseguire il test di un valore come nell'esempio riportato di seguito:

int? y = 10;
if (y != null)
{
    System.Console.WriteLine(y.Value);
}
else
{
    System.Console.WriteLine("Undefined");
}

Conversioni esplicite

È possibile eseguire il cast di un tipo nullable su un tipo regolare, in modo esplicito tramite cast oppure mediante la proprietà Value. Di seguito è riportato un esempio.

int? n = null;

//int m1 = n;      // Will not compile.
int m2 = (int)n;   // Compiles, but will create an exception if n is null.
int m3 = n.Value;  // Compiles, but will create an exception if n is null.

Se è stata definita una conversione specifica tra due tipi di dati, sarà possibile utilizzare la stessa conversione anche con le versioni nullable di questi tipi.

Conversioni implicite

Una variabile di tipo nullable può essere impostata su null con la parola chiave null, come illustrato nell'esempio riportato di seguito:

int? n1 = null;

La conversione da un tipo ordinario a un tipo nullable è implicita.

int? n2;
n2 = 10;  // Implicit conversion.

Operatori

Con i tipi nullable è anche possibile utilizzare gli operatori unari e binari predefiniti, nonché gli eventuali operatori definiti dall'utente disponibili per i tipi di valore esistenti. Se gli operandi sono null, questi operatori generano un valore null. In caso contrario, per calcolare il risultato l'operando utilizza il valore contenuto. Di seguito è riportato un esempio.

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

a++;         // Increment by 1, now a is 11.
a = a * 10;  // Multiply by 10, now a is 110.
a = a + b;   // Add b, now a is null.

Quando si eseguono confronti con tipi nullable, se il valore di uno dei tipi nullable è null e l'altro no, tutti i confronti restituiscono false ad eccezione di != (diverso da). È importante non presupporre che, poiché un particolare confronto restituisce false, il caso opposto restituisca true. Nell'esempio seguente 10 non è maggiore di, minore di o uguale a null. Solo num1 != num2 restituisce true.

int? num1 = 10;
int? num2 = null;
if (num1 >= num2)
{
    Console.WriteLine("num1 is greater than or equal to num2");
}
else
{
    // This clause is selected, but num1 is not less than num2.
    Console.WriteLine("num1 >= num2 returned false (but num1 < num2 also is false)");
}

if (num1 < num2)
{
    Console.WriteLine("num1 is less than num2");
}
else
{
    // The else clause is selected again, but num1 is not greater than
    // or equal to num2.
    Console.WriteLine("num1 < num2 returned false (but num1 >= num2 also is false)");
}

if (num1 != num2)
{
    // This comparison is true, num1 and num2 are not equal.
    Console.WriteLine("Finally, num1 != num2 returns true!");
}

// Change the value of num1, so that both num1 and num2 are null.
num1 = null;
if (num1 == num2)
{
    // The equality comparison returns true when both operands are null.
    Console.WriteLine("num1 == num2 returns true when the value of each is null");
}

/* Output:
 * num1 >= num2 returned false (but num1 < num2 also is false)
 * num1 < num2 returned false (but num1 >= num2 also is false)
 * Finally, num1 != num2 returns true!
 * num1 == num2 returns true when the value of each is null
 */

Un confronto di uguaglianze di due tipi nullable che sono entrambi null restituisce true.

OperatoreOperatore

L'operatore ?? definisce un valore predefinito che viene restituito quando un tipo nullable viene assegnato a un tipo non nullable.

int? c = null;

// d = c, unless c is null, in which case d = -1.
int d = c ?? -1;

Questo operatore può essere utilizzato anche con più tipi nullable. Di seguito è riportato un esempio.

int? e = null;
int? f = null;

// g = e or f, unless e and f are both null, in which case g = -1.
int g = e ?? f ?? -1;

Tipotype

Il tipo nullable bool? può contenere tre valori diversi: true, false e null. Per informazioni sull'esecuzione del cast da un tipo bool? a un tipo bool, vedere Procedura: eseguire il cast sicuro da bool? a bool (Guida per programmatori C#).

I valori booleani nullable sono come il tipo di variabile booleano utilizzato in SQL. Per verificare che i risultati prodotti da & e | siano coerenti con il tipo booleano a tre valori di SQL, sono disponibili i seguenti operatori predefiniti:

bool? operator &(bool? x, bool? y)

bool? operator |(bool? x, bool? y)

I risultati di questi operatori sono elencati nella tabella riportata di seguito:

X

y

x&y

x|y

true

true

true

true

true

false

false

true

true

null

null

true

false

true

false

true

false

false

false

false

false

null

false

null

null

true

null

true

null

false

false

null

null

null

null

null

Vedere anche

Riferimenti

Tipi nullable (Guida per programmatori C#)

Conversione boxing di tipi nullable (Guida per programmatori C#)

Concetti

Guida per programmatori C#