1. Null-Koaleszenz-Operator (??)
Dein Wissen über nullable-Typen ist nicht komplett, wenn du keine knackigen und sicheren Konstrukte schreiben kannst. In C# gibt es dafür zwei mega nützliche Operatoren: Null-Koaleszenz (??) und Null-Conditional-Operator (?.).
Der Operator ?? erlaubt dir, einen "Standardwert" für eine Variable zu setzen, die null sein kann.
Stell dir vor, du hast einen Benutzernamen, der null sein kann. Und wenn er wirklich null ist, willst du "Gast" anzeigen. Beispiel:
string userName = null;
string displayName = userName != null ? userName : "Gast";
Mit dem Operator ?? geht das noch kompakter:
string userName = null;
string displayName = userName ?? "Gast";
So funktioniert's:
- Wenn der Ausdruck links nicht null ist, wird er als Ergebnis zurückgegeben.
- Wenn links null steht, wird der Wert rechts genommen.
Noch ein paar Beispiele:
int? age = null;
int displayAge = age ?? -1; // -1 — Standardwert
Console.WriteLine(displayAge); // Gibt -1 aus
string input = null;
string name = input ?? "Gast";
Console.WriteLine($"Hallo, {name}!"); // Hallo, Gast!
Operator-Chaining
Du kannst ?? auch in einer Kette verschachteln:
string result = str1 ?? str2 ?? "Standardwert";
Wenn str1 nicht null ist, wird er genommen. Sonst str2, und wenn der auch null ist, dann der String "Standardwert".
2. Null-Conditional-Operator (?.)
Noch so eine typische Situation: Du willst eine Methode aufrufen oder auf eine Eigenschaft eines Objekts zugreifen, aber nur, wenn das Objekt selbst nicht null ist. Beispiel:
User user = null;
string displayName = user != null ? user.Name : null;
Mit dem Operator ?. geht das viel einfacher:
User user = null;
string displayName = user?.Name;
Wenn das Objekt user null ist, gibt der Ausdruck keinen Fehler, sondern einfach null zurück.
Beispiele:
User user = null;
// Ohne ?. — gibt's einen Fehler
// Console.WriteLine(user.Name); // NullReferenceException
Console.WriteLine(user?.Name); // Sicher — gibt leere Zeile oder nichts aus
Console.WriteLine(user?.GetProfileInfo()); // Genauso
User[] users = null;
int? count = users?.Length; // null, wenn users == null
Operator-Ketten
Du kannst ganze "Ketten" bauen:
string domain = company?.Director?.Email?.Split('@')?[1];
Wenn irgendein Teil des Pfads null ist, gibt der Ausdruck null zurück, statt eine Exception zu werfen.
Kombination mit ??
Die Operatoren ?. und ?? funktionieren super zusammen:
string display = user?.Name ?? "Unbekannt";
Wenn user oder user.Name null sind, wird "Unbekannt" ausgegeben.
3. Was ist ! und wozu braucht man das?
Operator zum Unterdrücken von null-Warnungen
In modernen C#-Versionen (mit aktiviertem NRT) warnt dich der Compiler, wenn du auf eine Variable zugreifst, die null sein könnte. Aber manchmal bist du dir sicher, dass alles passt. Dann kommt der Suppressions-Operator ! ins Spiel.
string? possibleNull = GetUserNameMaybeNull();
Console.WriteLine(possibleNull.Length); // Warnung: könnte null sein
Console.WriteLine(possibleNull!.Length); // Compiler bleibt still, aber wenn da null ist — Exception!
Wichtig: ! schützt dich nicht vor Fehlern — er sagt dem Compiler nur "Vertrau mir". Wenn die Variable wirklich null ist, gibt's eine NullReferenceException.
Wann du ihn besser nicht benutzt
Benutze ! nicht blind. Guter Stil ist, ihn möglichst selten einzusetzen. Besser ist es, den Code so zu bauen, dass null entweder unmöglich ist oder explizit behandelt wird.
4. default — wie du den "Standardwert" eines Typs bekommst
Manchmal willst du einfach eine Variable auf den Anfangszustand zurücksetzen, besonders wenn du nicht manuell 0, false oder null schreiben willst.
Dafür gibt's das Schlüsselwort default.
int a = default; // a == 0
bool flag = default; // flag == false
string s = default; // s == null
double? d = default; // d == null
In deiner Mini-App kannst du zum Beispiel den Namen oder das Alter zurücksetzen:
userName = default; // null
userAge = default; // null (wenn userAge ein int? ist)
5. Unterschiede und Feinheiten: ?, !, default
Selbst erfahrene Entwickler sind manchmal verwirrt, wenn sie ?, ! und default nebeneinander sehen. Lass uns klären, was was ist.
? — du erlaubst null
- Für Werttypen: int? x — jetzt kann x null sein.
- Für Referenztypen: string? s — du sagst explizit, dass die Variable null sein darf (im NRT-Modus).
! — du behauptest, dass null nicht vorkommt
- user!.Name — du versprichst dem Compiler, dass user garantiert nicht null ist.
- Funktioniert nur im Nullable Reference Types Modus.
default — du willst den "Standardwert"
- int x = default; — x wird 0
- string s = default; — s wird null
Vergleich:
| Syntax | Was ist das? | Wo funktioniert's? | Was hat das mit null zu tun? |
|---|---|---|---|
|
Nullable Werttyp | Überall | Kann null zugewiesen werden |
|
Nullable Referenztyp (NRT) | Im NRT-Modus | Kann null zugewiesen werden |
|
Null-forgiving operator | Im NRT-Modus | Unterdrückt Warnung |
|
Standardwert | Überall | Für Referenztypen — das ist null |
6. Typische Fehler bei der Verwendung von ?, ! und default
Fehler Nr. 1: Man denkt, dass ! null "heilt".
In Wirklichkeit sorgt ! nur dafür, dass der Compiler nicht meckert. Wenn der Wert trotzdem null ist, crasht das Programm mit einer NullReferenceException.
Fehler Nr. 2: Man vergisst, .HasValue zu prüfen, bevor man .Value verwendet.
Besonders bei int?, bool? und anderen nullable-Typen. Ohne diese Prüfung gibt's eine InvalidOperationException.
Fehler Nr. 3: Man benutzt default dort, wo eigentlich eine "besondere" Null-Bedeutung gebraucht wird.
Zum Beispiel können 0 oder false legitime Werte sein und nicht als "leer" gemeint sein. Das kann zu logischen Fehlern führen.
Fehler Nr. 4: Man verwendet ? für Referenztypen im NRT-Modus nicht — oder übertreibt es damit.
Manche vergessen das ? und der Compiler spuckt lauter Warnungen aus. Andere wiederum klatschen überall ? hin, auch da, wo null nie vorkommt. Beides macht den Code schwerer lesbar und weniger zuverlässig.
GO TO FULL VERSION