Wer rechnet schon damit?

Ich gebe zu der Titel ist mal wieder ein Wortspiel. Ich habe jetzt schon mal damit gerechnet: und zwar mit Werten in C#, die ’null‘ zulassen. Doch mit den daraus resultierenden Problemen habe ich nicht gerechnet.

Typen die ’null‘ zulassen

Vorab will ich kurz auf die Nullable Typen eingehen. Jeder kennt int, float, double, bool, … u.s.w. Diese eignen sich hervorragend für die dafür vorgesehenen Einsatzzwecke. Was man aber bei allen nicht machen kann: null zuweisen. Doch auch das ist möglich. Was man dazu braucht ist ein „?“.

int? wert = null;
if (wert.HasValue)
{
    int wertNeu = wert.Value;
}

Einsatzzweck: z.B. wenn man Werte aus der Datenbank übernehmen und auch DBNull abbilden möchte. Wobei viele vermutlich für Felder mit dem Typ int, bigint, bool … keine NULL values zulassen werden.

Das kann passieren

Dann sehen wir uns doch mal ein paar Beispiele an.

int? wertA = 0;
int? wertB = 0;
 
int? wertC = wertA + wertB;
Console.WriteLine("Das Ergebnis ist "+wertC);

Im ersten Beispiel gab es noch nichts zu beachten.
Ausgabe: Das Ergebnis ist 0

Beim 2.Beispiel sieht es da schon anders aus.

int? wertA = 0;
int? wertB = null;
 
int? wertC = wertA + wertB;
Console.WriteLine("Das Ergebnis ist "+wertC);

Die Ausgabe: Das Ergebnis ist
Man sieht schon worauf ich hinaus will. Das Ergebnis ist nämlich hier nicht 0, sondern null.

Wenn einem das Ergebnis vom 2.Beispiel klar ist, wird man auf sowas nicht mehr hereinfallen. Beispiel 3:

int? summe = null;
List<int?> werte = new List<int?>();
werte.Add(1);
werte.Add(2);
werte.Add(3);
werte.Add(4);
werte.Add(5);
 
for (int i=0; i<werte.Count; i++)
{
    summe += werte[i];
}
Console.WriteLine("Das Summe ist "+summe);

Die Ausgabe: Das Summe ist
Wieder null, denn wir addieren zu null weitere Zahlen. Das Ergebnis ist immer null.

Am 4.Beispiel sieht man dann auch gleich, wie schön sich der Fehler verstecken kann:

int? summe = 0;
List<int?> werte = new List<int?>();
werte.Add(1);
werte.Add(2);
werte.Add(null);
werte.Add(4);
werte.Add(5);
 
for (int i=0; i<werte.Count; i++)
{
    summe = summe.GetValueOrDefault(0) + werte[i];
}
 
Console.WriteLine("Das Summe ist: "+summe);

Ausgabe: Das Summe ist: 9
In diesem Beispiel wurde bereits dazu gelernt. Denn beim aufsummieren verwende ich .GetValueOrDefault(0). Sprich falls die Summe null wäre, wird als Wert 0 verwendet, was ja das neutrale Element einer Addition darstellt. Doch leider wäre .GetValueOrDefault(0) auch bei den einzelnen Werten von Vorteil gewesen. Denn dann wäre die Summe 12 und nicht wie in dem Beispiel nur 9.

Best practice

Wenn es nicht sein muss, würde ich auf die ‚Nullable‘ Funktion verzichten. Wer darauf angewiesen ist, dem kann ich nur empfehlen immer .GetValueOrDefault(0) zu verwenden. (wobei es natürlich vom Anwendungsfall abhängt, ob der default Wert 0 sein soll). Damit stellt man sicher, dass man nicht in die null-Falle tappt.
Es gibt auch noch eine Alternative zu .GetValueOrDefault(0):

int? wertA = null;
int ergebnis = wertA ?? 0;
Console.WriteLine("Das Summe ist: "+ergebnis);

Ausgabe: Das Summe ist: 0

Falls jemand den ?? Operator nicht kennt: Ist der Wert des Objektes nicht null, so wird dieser zurückgegeben. Ansonsten wird der Wert hinter ‚??‘ zurückgegeben. In diesem Fall 0;

Ansonsten kann man natürlich, wie in der Einleitung gezeigt, auch ganz klassisch mit .HasValue abprüfen ob überhaupt ein Wert verfügbar ist und entsprechend darauf reagieren, falls dies nicht Fall sein sollte.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert