Verwenden von auf NULL festlegbaren Typen (C# Programmierhandbuch)

Auf NULL festlegbare Typen können alle Werte eines zugrundeliegenden Typs und einen zusätzlichen NULL-Wert darstellen. Auf NULL festlegbare Typen können auf zwei verschiedene Arten deklariert werden:

System.Nullable<T> variable

  • oder -

T? variable

T ist der zugrundeliegende Typ des Typs, der NULL-Werte zulässt. T kann jeder Werttyp, auch struct, sein; allerdings kann es kein Verweistyp sein.

Denken Sie z.B. an eine normalen Boolesche Variable, die zwei Werte aufweisen kann: TRUE und FALSE; so ähnlich verhält es sich auch mit dem Einsatz eines Typs, der NULL-Werte zulässt. Es gibt keinen Wert, der für „nicht definiert“ steht. In den meisten Programmierungsanwendungen – allen voran Datenbankinteraktionen – können Variablen in einem nicht definierten Zustand vorkommen. Ein Feld in einer Datenbank kann z.B. die Werte TRUE und FALSE enthalten; ebenso kann es aber auch gar keinen Wert enthalten. Ebenso können Verweistypen auf null festgelegt werden, um zu kennzeichnen, dass sie nicht initialisiert wurden.

Durch diese Ungleichheit kann weiteres Programmieren erforderlich sein: zusätzliche Variablen zum Speichern von Zustandsinformationen, der Einsatz von besonderen Werten usw. Mit dem Modifizierer für Typen, die NULL-Werte zulassen, kann C# value-type-Variablen erstellen, die einen nicht definierten Wert kennzeichnen.

Beispiele für Typen, die NULL-Werte zulassen

Jeder Werttyp kann als Grundlage für einen Typ, der NULL-Werte zulässt, verwendet werden. Beispiel:

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

Member von Typen, die NULL-Werte zulassen

Jede Instanz eines Typs, der auf NULL festgelegt werden kann, hat zwei öffentliche schreibgeschützte Eigenschaften:

  • HasValue

    HasValue ist vom Typ bool. Es wird auf true festgelegt, wenn die Variable einen Wert enthält, der ungleich NULL ist.

  • Value

    Value hat denselben Typ wie der zugrunde liegende Typ. Wenn HasValue true ist, enthält Value einen sinnvollen Wert. Wenn HasValue auf false festgelegt ist, wird bei Zugriff auf Value eine <xref:System.InvalidOperationException> ausgelöst.

Der HasValue-Member in diesem Beispiel wird dazu verwendet, zu prüfen, ob eine Variable einen Wert enthält, bevor er diesen anzeigt.

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

Das Prüfen auf einen Wert kann auch wie im folgenden Beispiel durchgeführt werden:

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

Explizite Konvertierungen

Ein Typ, der NULL-Werte zulässt, kann in einen gängigen Typ umgewandelt werden; dies können Sie entweder durch eine explizite Umwandlung oder mithilfe der Value-Eigenschaft erzielen. Beispiel:

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.

Wenn eine benutzerdefinierte Konvertierung zwischen zwei Datentypen definiert ist, kann die gleiche Konvertierung auch mit der Version dieser Datentypen verwendet werden, die NULL-Werte zulassen.

Implizite Konvertierungen

Eine Variable mit einem Typ, der NULL-Werte zulässt, kann wie in folgendem Beispiel mit dem Schlüsselwort null auf NULL festgelegt werden:

int? n1 = null;

Die Konvertierung von einem gängigen in einen auf NULL-festlegbaren Typ ist implizit.

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

Operatoren

Die vordefinierten unären und binären Operatoren und alle benutzerdefinierten Operatoren für Werttypen können auch von auf NULL festlegbaren Typen verwende werden. Die Operatoren erzeugen einen NULL-Wert, wenn die Operanden NULL sind; andernfalls verwenden die Operatoren den enthaltenen Wert zur Berechnung eines Ergebnisses. Zum Beispiel:

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.

Wenn Sie Vergleiche mit auf NULL-festlegbaren Typen durchführen, ergeben alle Vergleiche false, nur != nicht (ungleich), wenn der Wert von lediglich einem auf NULL festlegbaren Wert NULL ist. Es ist wichtig, dass Sie nicht davon ausgehen, dass der entgegengesetzte Fall true zurückgeben würde, nur wenn ein Vergleich false zurückgibt. Im folgenden Beispiel ist 10 weder größer noch kleiner noch gleich NULL. Nur num1 != num2 ergibt 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
 */

Ein Gleichheitsvergleich zweier auf NULL festlegbarer Typen, die beide NULL sind, ergibt true.

Der ??- Operator

Der ??-Operator definiert einen Standardwert, der zurückgegeben wird, wenn ein auf NULL festlegbarer Typ einem nicht auf NULL festlegbaren Typ zugewiesen wird.

int? c = null;

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

Dieser Operator kann auch mit mehreren auf NULL festlegbaren Typen verwendet werden. Zum Beispiel:

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;

Der „bool?“-Typ

Der bool?-Typ, der NULL-Werte zulässt, kann drei verschiedene Werte enthalten: TRUE, FALSE und NULL. Weitere Informationen zur Umwandlung von „bool?“ in „bool“ finden Sie unter Vorgehensweise: Sichere Umwandlung von bool? in bool.

Boolesche Werte, die auf NULL festgelegt werden können, verhalten sich ähnlich wie der in SQL verwendete Boolesche Variablentyp. Folgende vordefinierte Operatoren stehen zur Verfügung, um sicherzustellen, dass die von den Operatoren & und | erzeugten Ergebnisse zu dem dreiwertigen Booleschen Typ in SQL passen:

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

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

Die Ergebnisse dieser Operatoren sind in der folgenden Tabelle aufgeführt:

X u 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

Siehe auch

C#-Programmierhandbuch
Typen, die NULL-Werte zulassen
Boxing von Typen mit NULL-Werten
Auf NULL festlegbare Werttypen