Nullable ToString ()

142

Wszędzie widzę konstrukcje takie jak:

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

Dlaczego nie użyć po prostu:

string test = myVar.ToString();

Czy to nie jest dokładnie to samo? Przynajmniej Reflector mówi, że:

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

Czy to prawda (krótsza wersja), czy czegoś mi brakuje?

IamDeveloper
źródło
1
Nie widziałem takiego kodu :)
tymtam

Odpowiedzi:

112

Masz całkowitą rację. Również w tym pytaniu sugerowane jest poprzednie rozwiązanie, podczas gdy w rzeczywistości nikt nie zauważa, że ToString()już daje prawidłową odpowiedź.

Może argument za bardziej opisowym rozwiązania jest czytelność: Podczas rozmowy telefonicznej ToString()na coś, co jest rzekomo być null, zwykle oczekująNullReferenceException , chociaż tutaj nie jest wyrzucane.

Tomas Vana
źródło
21
Właściwie zauważyły ​​co najmniej dwie osoby: Eric Lippert i Johannes Rössel.
Jon Skeet
7
Chociaż jestem pewien, że nie to miałeś na myśli, odniesienie nie jest tutaj puste. Nullable <T> jest typem wartości. Dlatego dzwonienie ToString()działa bez NullReferenceExceptionrzucania się.
Thorarin
2
Gdyby taka była mentalność, można by się spodziewać, że .HasValuenadal rzucisz ten wyjątek.
Extragorey
Innym powodem, dla którego ludzie używają pełnej wersji, może być parzystość z wyrażeniami, takimi jak myNullableDateTime.HasValue ? myNullableDateTime.Value.ToString("d") : nullsytuacja, w której rozpakowany obiekt jest potrzebny, aby uzyskać dostęp do żądanej ToStringmetody. Oczywiście jest na to również bardziej zwięzłe rozwiązanie:$"{myNullableDateTime:d}"
Extragorey
14

Myślę, że wiele osób ma takie kontrole, ponieważ nie jest to naturalne zachowanie obiektu, który może mieć wartość zerową.

Andrew Bezzub
źródło
@Andrew, zgodził się, ponieważ ludzie (jak ja) myślą na początku, że rzucą wyjątek.
Nathan Koop
1
Nie miałem pojęcia, że ​​to było zachowanie. Zdecydowanie pomyślałbym, że każda konstrukcja, która zwraca prawdę dla (x == null), również wyrzuciłaby NullReferenceException, jeśli wywołasz x.ToString ().
Dan Bryant
5

Nie, masz rację, krótsza wersja jest taka sama, jak to, co inni zrobili w tym względzie. Inną konstrukcją, której często używam zamiast trójskładnika z wartościami null, jest operator koalescencji zerowej. który również chroni Cię przed zerami. W przypadku ToString () nie jest to konieczne (jak zauważyłeś), ale dla domyślnych wartości int (na przykład) działa ładnie, np:

int page = currentPage ?? 1;

która pozwala wykonać wszystkie operacje na liczbach całkowitych na stronie bez uprzedniego jawnego sprawdzenia wartości null i wywołania wartości w currentPage (gdzie currentPage jest int? być może przekazanym jako parametr)

Paweł
źródło
5

Wiem, długo po tym, jak było to istotne, ale ... Podejrzewam, że to dlatego, że w przypadku typów dopuszczających wartość null, takich jak int? metoda .ToString () nie pozwala na używanie ciągów formatujących. Zobacz, jak sformatować DateTime dopuszczającą wartość null za pomocą ToString ()? . Być może w oryginalnym kodzie znajdował się ciąg formatu w .ToString () lub być może koder zapomniał, że .ToString () bez łańcucha formatującego jest nadal dostępny dla typów dopuszczających wartość null.

outis nihil
źródło
3

może jest to po prostu podążanie za wzorem? lub nie znają zaplecza. masz rację kod jest dokładnie taki sam. możesz nawet zrobić:

int? i = null;
i.ToString(); //No NullReferenceException
Andrey
źródło
Może być konieczne skorzystanie z długiej trasy, jeśli ToString () musi mieć niezmienną kulturę, ponieważ wartości null nie mają jej w swoim menu.
Ε Г И І И О
1

int?jest lukrem składni, który upraszcza deklarację zmiennej dopuszczającej wartość null. To jest to samo co Nullable<int>.

Jeśli więc przyjrzysz się implementacji ToString()metody for Nullable<T> (patrz poniżej) , możesz zauważyć, że zwraca ona pusty łańcuch w przypadku, gdy nie ma wartości.

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

Co mówi MSDN:

Metoda Nullable.ToString

Zwraca tekstową reprezentację wartości bieżącego obiektu Nullable, jeśli właściwość HasValue ma wartość true, lub pusty ciąg („”), jeśli właściwość HasValue ma wartość false.

Zatem poniższy kod wypisze pusty ciąg do konsoli zamiast rzucać ArgumentNullExceptionwyjątek.

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