Verwenden von auf NULL festlegbaren Typen (C# Programmierhandbuch)

Typen, die auf NULL festgelegt werden können, können alle Werte des zugrunde liegenden Typs und einen zusätzlichen null-Wert darstellen. Typen, die auf NULL festgelegt werden können, werden auf zwei verschiedene Arten deklariert:

System.Nullable<T> variable

– oder –

T? variable

T ist der zugrunde liegende Typ des Nullable-Typs. T kann ein beliebiger Wert einschließlich struct sein; es kann kein Verweistyp sein.

Nehmen Sie als Beispiel für das Einsatzgebiet eines Typs, der auf NULL festgelegt werden kann, eine boolesche Variable. Sie kann zwei Werte annehmen: true und false. Es gibt keinen Wert, der "nicht definiert" angibt. In vielen Programmieranwendungen, besonders bei Datenbankinteraktionen, können Variablen in einem nicht definierten Zustand existieren. Ein Feld in einer Datenbank kann z. B. den Wert true oder false enthalten, aber es kann auch überhaupt keinen Wert enthalten. Auf ähnliche Weise können Referenztypen auf null festgelegt werden, um anzugeben, dass sie nicht initialisiert sind.

Diese Ungleichheit kann zu zusätzlichem Programmiereraufwand führen – beispielsweise zusätzliche Variablen zum Speichern von Zustandsinformationen, spezielle Werte usw. Der Modifizierer für Typen, die auf NULL festgelegt werden können, ermöglicht in C# das Erstellen von Werttypvariablen, die einen nicht definierten Wert angeben.

Beispiele von Typen, die auf NULL festgelegt werden können

Jeder Werttyp kann als Grundlage für einen Typ verwenden werden, der auf NULL festgelegt werden kann. Beispiele:

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

Die Member der Typen, die auf NULL festgelegt werden können

Jede Instanz eines auf NULL festlegbaren Typs besitzt zwei öffentliche schreibgeschützte Eigenschaften:

  • HasValue

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

  • Value

    Value hat denselben Typ wie der zugrunde liegende Typ. Wenn HasValue den Wert true hat, enthält Value einen sinnvollen Wert. Wenn HasValue den Wert false hat, löst das Zugreifen auf Value eine InvalidOperationException aus.

In diesem Beispiel wird mit dem HasValue-Member getestet, ob die Variable einen Wert enthält, bevor versucht wird, diese anzuzeigen.

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

Dieser Test kann auch wie in folgendem Beispiel ausgeführt werden:

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

Explizite Konvertierungen

Ein auf NULL festlegbarer Typ kann in einen regulären Typ umgewandelt werden. Dies kann entweder explizit mit einer Umwandlung oder mit der Value-Eigenschaft erfolgen. Beispiele:

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 festgelegt wird, kann dieselbe Konvertierung auch für auf NULL festlegbare Versionen dieser Datentypen verwendet werden.

Implizite Konvertierungen

Eine Variable eines auf NULL festlegbaren Typs kann mit dem Schlüsselwort null auf NULL festgelegt werden, wie im folgenden Beispiel gezeigt:

int? n1 = null;

Die Konvertierung von einem gewöhnlichen Typ in einen auf NULL festlegbaren Typ ist implizit.

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

Operatoren

Die vordefinierten unären und binären Operatoren sowie alle für Werttypen vorhandenen benutzerdefinierten Operatoren können auch von auf NULL festlegbaren Typen verwendet werden. Diese Operatoren generieren einen NULL-Wert, wenn die Operanden auf NULL festgelegt sind. Ansonsten verwendet der Operand den enthaltenen Wert, um das Ergebnis zu berechnen. Beispiele:

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 Typen ausführen, die NULL-Werte zulassen, und der Wert eines Typs NULL ist, der Wert des anderen Typs jedoch nicht, werden alle Vergleiche außer != (ungleich) als false ausgewertet. Daher sollt keinesfalls angenommen werden, dass wenn ein bestimmter Vergleich false zurückgibt, im entgegengesetzten Fall true zurückgegeben wird. Im folgenden Beispiel ist 10 weder größer als noch kleiner als noch gleich NULL. Nur num1 != num2 wird als true ausgewertet.

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 Typen, die NULL-Werte zulassen und beide NULL sind, wird als true ausgewertet.

Der ??Operator

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

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

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?-type

Der auf NULL festlegbare bool?-Typ kann drei verschiedene Werte enthalten: true, false und null. Weitere Informationen zur Umwandlung von einem bool?-Typ in einen bool-Typ finden Sie unter Gewusst wie: Sichere Umwandlung von bool? in bool (C#-Programmierhandbuch).

Auf NULL festlegbare boolesche Typen entsprechen den in SQL verwendeten Variablen vom Typ Boolean. Um sicherzustellen, dass die von & erstellten Ergebnisse und | Operatoren sind mit dem booleschen Typ mit drei Werten in SQL konsistent. Die folgenden vordefinierten Operatoren werden bereitgestellt:

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

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

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

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

Siehe auch

Referenz

Typen, die NULL-Werte zulassen (C#-Programmierhandbuch)

Boxing von Typen, die NULL-Werte zulassen (C#-Programmierhandbuch)

Konzepte

C#-Programmierhandbuch