Share via


Utilizzo dei tipi nullable (Guida per programmatori C#)

Aggiornamento: novembre 2007

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

-oppure-

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. 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. Esempio:

int? n = null;

//int m1 = n;      // Will not compile.
int m2 = (int)n;   // Compiles, but will create an exception if x is null.
int m3 = n.Value;  // Compiles, but will create an exception if x 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. 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 tra tipi nullable, se uno dei tipi è null il risultato sarà sempre false. È quindi importante non presupporre che, poiché un confronto è false, il caso opposto sia true. Esempio:

int? num1 = 10;
int? num2 = null;
if (num1 >= num2)
{
    System.Console.WriteLine("num1 is greater than or equal to num1");
}
else
{
    // num1 is NOT less than num2
}

La conclusione nell'istruzione else non è valida, perché num2 è null e pertanto non contiene un valore.

Il risultato del confronto tra due tipi nullable che sono entrambi null sarà sempre true.

Operatore ??

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. 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;

Tipo bool?

Il tipo nullable bool? può contenere tre valori diversi: true, false e null. For information about how to cast from a bool? to a bool, see 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 garantire che i risultati degli operatori & 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

Concetti

Guida per programmatori C#

Riferimenti

Tipi nullable (Guida per programmatori C#)

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