Nullable ToString ()

142

Ich sehe überall Konstruktionen wie:

int? myVar = null;
string test = myVar.HasValue ? myVar.Value.ToString() : string.Empty;

Warum nicht einfach verwenden:

string test = myVar.ToString();

Ist das nicht genau das gleiche? Zumindest sagt Reflector Folgendes:

public override string ToString()
{
  if (!this.HasValue)
  {
    return "";
  }
  return this.value.ToString();
}

Also, ist das richtig (die kürzere Version) oder fehlt mir etwas?

IamDeveloper
quelle
1
Ich habe Code wie diesen nicht gesehen :)
Tymtam

Antworten:

112

Du bist ganz richtig. Auch in dieser Frage wird die erstere Lösung vorgeschlagen, während niemand bemerkt, dass ToString()bereits die richtige Antwort vorliegt.

Vielleicht ist das Argument für die ausführlichere Lösung Lesbarkeit: Wenn Sie rufen ToString()auf etwas, das soll sein null, Sie in der Regel erwarten ein NullReferenceException, obwohl hier nicht geworfen wird.

Tomas Vana
quelle
21
Tatsächlich bemerkten mindestens zwei Personen: Eric Lippert und Johannes Rössel.
Jon Skeet
7
Ich bin mir zwar sicher, dass Sie das nicht gemeint haben, aber die Referenz ist hier nicht wirklich null. Nullable <T> ist ein Werttyp. Aus diesem Grund ToString()funktioniert das Anrufen, ohne dass NullReferenceExceptiones geworfen wird.
Thorarin
2
Wenn das die Mentalität wäre, würden Sie erwarten .HasValue, diese Ausnahme immer noch zu werfen.
Extragorey
Ein weiterer Grund, warum Benutzer die ausführliche Version verwenden, könnte die Parität mit Ausdrücken sein, z. B. myNullableDateTime.HasValue ? myNullableDateTime.Value.ToString("d") : nullwo Sie das entpackte Objekt benötigen, um auf die gewünschte ToStringMethode zuzugreifen . Natürlich gibt es auch dafür eine $"{myNullableDateTime:d}"
präzisere
14

Ich denke, dass viele Leute solche Prüfungen haben, weil es kein natürliches Verhalten eines Objekts ist, das einen Nullwert enthalten kann.

Andrew Bezzub
quelle
@ Andrew, stimmte zu, weil Leute (wie ich) zuerst denken, dass es eine Ausnahme werfen wird.
Nathan Koop
1
Ich hatte keine Ahnung, dass dies das Verhalten war. Ich hätte definitiv gedacht, dass jedes Konstrukt, das true für (x == null) zurückgibt, auch eine NullReferenceException auslösen würde, wenn Sie x.ToString () aufrufen.
Dan Bryant
5

Nein, Sie haben Recht, die kürzere Version ist die gleiche wie die, die andere Leute in dieser Hinsicht getan haben. Das andere Konstrukt, das ich häufig anstelle des ternären Konstrukts mit nullables verwende, ist der Null-Koaleszenzoperator. Das schützt Sie auch vor Nullen. Für ToString () ist es nicht erforderlich (wie Sie bereits betont haben), aber für Standard-Int-Werte (zum Beispiel) funktioniert es gut, z.

int page = currentPage ?? 1;

Auf diese Weise können Sie alle Ganzzahloperationen auf Seite ausführen, ohne zuerst explizit null zu prüfen und den Wert in currentPage aufzurufen (wobei currentPage ein int ist, das möglicherweise als Parameter übergeben wird).

Paul
quelle
5

Ich weiß, lange nachdem es relevant war, aber ... Ich vermute, es liegt daran, dass für nullbare Typen wie int? Mit der .ToString () -Methode können Sie keine Formatzeichenfolgen verwenden. Siehe Wie kann ich mit ToString () eine nullfähige DateTime formatieren? . Möglicherweise gab es im Originalcode eine Formatzeichenfolge in .ToString (), oder der Codierer hat vergessen, dass .ToString () ohne die Formatzeichenfolge für nullfähige Typen noch verfügbar war.

outis nihil
quelle
3

kann es sein, nur um Muster zu folgen? oder sie kennen das Backend nicht. Sie haben Recht, Code ist genau das gleiche. Sie können sogar tun:

int? i = null;
i.ToString(); //No NullReferenceException
Andrey
quelle
Möglicherweise müssen Sie den langen Weg gehen, wenn ToString () eine unveränderliche Kultur haben muss, da Nullables ihn nicht in ihrem Menü haben.
Г И І І
1

int?ist Syntaxzucker, der die Deklaration einer nullbaren Variablen vereinfacht. Es ist das gleiche wie Nullable<int>.

Wenn Sie sich also die Implementierung der ToString()Methode für Nullable<T> (siehe unten) ansehen , können Sie feststellen, dass sie eine leere Zeichenfolge zurückgibt, falls sie keinen Wert hat.

public struct Nullable<T> where T : struct
{
    public override string ToString()
    {
      if (!this.hasValue)
        return "";
      return this.value.ToString();
    }
}

Was MSDN sagt:

Nullable.ToString-Methode

Gibt die Textdarstellung des Werts des aktuellen Nullable-Objekts zurück, wenn die HasValue-Eigenschaft true ist, oder eine leere Zeichenfolge (""), wenn die HasValue-Eigenschaft false ist.

Der folgende Code gibt also eine leere Zeichenfolge an die Konsole aus, anstatt eine ArgumentNullExceptionAusnahme auszulösen .

static void Main(string[] args)
{
    int? a = null;
    Console.WriteLine(a.ToString()); // Prints empty string to console.
}
Aliaksei Maniuk
quelle