Nullable-Werttypen (C#-Referenz)
Ein Werttyp, der NULL zulässt (wie T?
) stellt alle Werte des zugrunde liegenden Werttyps T
und einen zusätzlichen NULL-Wert dar. Beispielsweise können Sie einer bool?
-Variablen einen der folgenden drei Werte zuweisen: true
, false
oder null
. Ein zugrunde liegender Werttyp T
darf selbst kein Nullable-Werttyp sein.
Jeder Nullable-Werttyp ist eine Instanz der generischen Struktur System.Nullable<T>. Sie können auf einen Nullable-Werttyp mit einem zugrunde liegenden Typ T
in einer der folgenden austauschbaren Formen verweisen: Nullable<T>
oder T?
.
Sie verwenden in der Regel einen Nullable-Werttyp, wenn Sie den nicht definierten Wert eines zugrunde liegenden Werttyps darstellen müssen. Beispielsweise kann ein boolescher Wert eine bool
-Variable nur true
oder false
sein. In einigen Anwendungen kann ein Variablenwert jedoch nicht definiert sein oder fehlen. Beispielsweise kann ein Datenbankfeld true
oder false
enthalten, oder es enthält gar keinen Wert, ist also NULL
. In diesem Szenario können Sie den bool?
-Typ verwenden.
Deklaration und Zuweisung
Da ein Werttyp implizit in den entsprechenden Nullable-Werttyp konvertiert werden kann, können Sie einer Variablen eines Nullable-Werttyps auf die gleiche Weise wie seinem zugrunde liegenden Werttyp einen Wert zuweisen. Sie können auch den null
-Wert zuweisen. Zum Beispiel:
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];
Der Standardwert eines Nullable-Werttyps stellt null
dar, es handelt sich also um eine-Instanz, deren Nullable<T>.HasValue-Eigenschaft false
zurückgibt.
Untersuchung einer Instanz eines Nullable-Werttyps
Sie können den is
-Operator mit einem Typmuster verwenden, um eine Instanz eines Nullable-Werttyps für null
zu untersuchen und einen Wert eines zugrunde liegenden Typs abzurufen:
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
Sie können immer die folgenden schreibgeschützten Eigenschaften verwenden, um einen Wert einer Variablen des Nullable-Werttyps zu untersuchen und abzurufen:
Nullable<T>.HasValue gibt an, ob eine Instanz des Nullable-Werttyps über einen Wert des zugrunde liegenden Typs verfügt.
Nullable<T>.Value ruft den Wert eines zugrunde liegenden Typs ab, wenn HasValue
true
ist. Wenn HasValuefalse
ist, löst die Value-Eigenschaft eine InvalidOperationException aus.
Im folgenden Beispiel wird mit der HasValue
-Eigenschaft überprüft, ob die Variable einen Wert enthält. Erst danach erfolgt die Anzeige:
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
Sie können eine Variable eines Nullable-Werttyps wie im folgenden Beispiel gezeigt auch mit null
anstelle der HasValue
-Eigenschaft vergleichen:
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
Konvertieren eines Nullable-Werttyps in einen zugrunde liegenden Typ
Wenn Sie einen Wert eines Nullable-Werttyps einer Variablen eines Nicht-Nullable-Werttyps zuweisen möchten, müssen Sie möglicherweise den zuzuweisenden Wert anstelle von null
angeben. Verwenden Sie zu diesem Zweck den NULL-Sammeloperator ??
(Sie können auch die Nullable<T>.GetValueOrDefault(T)-Methode für denselben Zweck verwenden):
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
Wenn Sie den Standardwert des zugrunde liegenden Werttyps anstelle von null
verwenden möchten, verwenden Sie die Nullable<T>.GetValueOrDefault()-Methode.
Sie können einen Nullable-Werttyp wie im folgenden Beispiel gezeigt auch explizit in einen Non-Nullable-Typ umwandeln:
int? n = null;
//int m1 = n; // Doesn't compile
int n2 = (int)n; // Compiles, but throws an exception if n is null
Wenn der Wert eines Nullable-Typs zur Laufzeit null
ist, wird durch die explizite Umwandlung eine InvalidOperationException ausgelöst.
Ein Nicht-Nullable-Werttyp T
kann implizit in den entsprechenden Nullable-Werttyp T?
konvertiert werden.
„Lifted“ Operatoren
Die vordefinierten unären und binären Operatoren oder alle überladenen Operatoren, die von einem Werttyp T
unterstützt werden, werden auch vom entsprechenden Werttyp T?
unterstützt, der NULL zulässt. Durch diese Operatoren (auch als „lifted“ Operatoren bezeichnet) wird null
generiert, wenn mindestens ein Operand null
ist. Andernfalls verwendet der Operator die enthaltenen Werte seiner Operanden zur Berechnung des Ergebnisses. Zum Beispiel:
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
Hinweis
Für den bool?
-Typ gelten für die vordefinierten Operatoren &
und |
nicht die in diesem Abschnitt beschriebenen Regeln. Die Auswertung eines Operators kann auch dann einen anderen Wert als NULL ergeben, wenn einer der beiden Operanden null
ist. Weitere Informationen finden Sie im Abschnitt Boolesche logische Operatoren, die NULL-Werte zulassen im Artikel Boolesche logische Operatoren.
Für die Vergleichsoperatoren <
, >
, <=
und >=
ist das Ergebnis false
, wenn einer oder beide Operanden null
sind. Andernfalls werden die enthaltenen Werte von Operanden verglichen. Falsch wäre die Annahme, dass im Fall des Rückgabewerts false
für einen bestimmten Vergleich (beispielsweise <=
) der gegenteilige Vergleich (>
) true
zurückgibt. Das folgende Beispiel zeigt, dass 10
- weder größer als oder gleich
null
- noch kleiner als
null
ist.
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
Für den Gleichheitsoperator ==
ist das Ergebnis true
, wenn beide Operanden null
sind. Das Ergebnis ist false
, wenn nur einer der Operanden null
ist. Andernfalls werden die enthaltenen Werte von Operanden verglichen.
Für den Ungleichheitsoperator !=
ist das Ergebnis false
, wenn beide Operanden null
sind. Das Ergebnis ist true
, wenn nur einer der Operanden null
ist. Andernfalls werden die enthaltenen Werte von Operanden verglichen.
Wenn eine benutzerdefinierte Konvertierung zwischen zwei Werttypen vorhanden ist, kann die gleiche Konvertierung auch zwischen den entsprechenden Nullable-Werttypen verwendet werden.
Boxing und Unboxing
Das Boxing einer Instanz eines Nullable-Werttyps T?
erfolgt folgendermaßen:
- Wenn HasValue
false
zurückgibt, wird der Nullverweis erstellt. - Wenn HasValue
true
zurückgibt, wird nicht für eine Instanz von Nullable<T>, sondern für den entsprechenden Wert des zugrunde liegenden WerttypsT
Boxing durchgeführt.
Sie können den Werttyp, für den das Boxing durchgeführt wurde, vom Werttyp T
mittels Unboxing in den entsprechenden Nullable-Werttyp T?
konvertieren, wie im folgenden Beispiel gezeigt wird:
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
Identifizieren eines Nullable-Werttyps
Das folgende Beispiel zeigt, wie Sie bestimmen können, ob eine System.Type-Instanz einen konstruierten Nullable-Werttyp darstellt, d.h. den System.Nullable<T>-Typ mit einem angegebenen Typparameter 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
Wie Sie im Beispiel sehen können, wird der Operator typeof verwendet, um eine System.Type-Instanz zu erstellen.
Wenn Sie bestimmen möchten, ob eine Instanz einen Nullable-Werttyp aufweist, verwenden Sie nicht die Object.GetType-Methode, um eine Type-Instanz abzurufen, die mit dem vorangehenden Code überprüft werden soll. Wenn Sie die Object.GetType-Methode in einer Instanz eines Nullable-Werttyps aufrufen, wird die Instanz in Objectgeschachtelt. Da das Schachteln einer nicht-NULL-Instanz von einem Nullable-Werttyp dem Schachteln eines Werts des zugrunde liegenden Typs entspricht, gibt GetType eine Type-Instanz zurück, die den zugrunde liegenden Typ eines Nullable-Werttyps darstellt:
int? a = 17;
Type typeOfA = a.GetType();
Console.WriteLine(typeOfA.FullName);
// Output:
// System.Int32
Verwenden Sie außerdem nicht den Operator is, um zu ermitteln, ob eine Instanz einem Nullable-Werttyp entspricht. Wie im folgenden Beispiel veranschaulicht wird, können Sie die Typen einer Instanz eines Nullable-Werttyps und die zugrunde liegende Typinstanz nicht mithilfe des is
-Operators unterscheiden:
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?
Verwenden Sie stattdessen den Nullable.GetUnderlyingType aus dem ersten Beispiel und den typeof-Operator, um zu überprüfen, ob eine Instanz einen Nullwerte zulassenden Werttyp aufweist.
Hinweis
Die in diesem Abschnitt beschriebenen Methoden sind im Fall von Nullable-Verweistypen nicht anwendbar.
C#-Sprachspezifikation
Weitere Informationen finden Sie in den folgenden Abschnitten der C#-Sprachspezifikation:
- Nullable-Typen
- „Lifted“ Operatoren
- Implizite Nullable-Konvertierungen
- Explizite Nullable-Konvertierungen
- „Lifted“ Konvertierungsoperatoren
Weitere Informationen
- What exactly does 'lifted' mean? (Was bedeutet „Lifted“ genau?)
- System.Nullable<T>
- System.Nullable
- Nullable.GetUnderlyingType
- Nullwerte zulassende Verweistypen