150

I see everywhere constructions like:

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

Why not use simply:

string test = myVar.ToString();

Isn't that exactly the same ? At least Reflector says that:

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

So, is that correct (the shorter version) or am I missing something?

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
IamDeveloper
  • 5,156
  • 6
  • 34
  • 50

6 Answers6

118

You are quite correct. Also in this question, the former solution is suggested while nobody actually notices ToString() already gives the correct answer.

Maybe the argument for the more verbose solution is readability: When you call ToString() on something that is supposed to be null, you usually expect a NullReferenceException, although here it isn't thrown.

Community
  • 1
  • 1
Tomas Vana
  • 18,317
  • 9
  • 53
  • 64
  • 21
    Actually, at least two people noticed: Eric Lippert and Johannes Rössel. – Jon Skeet Mar 15 '10 at 17:22
  • 8
    While I'm sure that isn't what you meant, the reference isn't actually null here. Nullable is a value type. This is why calling `ToString()` works without any `NullReferenceException` being thrown. – Thorarin Sep 17 '14 at 14:40
  • 4
    If that was the mentality, you'd expect `.HasValue` to still throw that exception. – Extragorey Apr 18 '18 at 00:13
  • 1
    Another reason people use the verbose version could be for parity with expressions like `myNullableDateTime.HasValue ? myNullableDateTime.Value.ToString("d") : null` where you do need the unwrapped object to access the desired `ToString` method. Of course, there's a more concise solution for that too: `$"{myNullableDateTime:d}"` – Extragorey Apr 18 '18 at 00:18
14

I think that many people have such checks because it is not a natural behavior of an object that can hold null value.

Andrew Bezzub
  • 15,744
  • 7
  • 51
  • 73
  • @Andrew, agreed, because people (like me) think at first that it will throw an exception. – Nathan Koop Mar 15 '10 at 17:16
  • 1
    I had no idea this was the behavior. I definitely would have thought that any construct which returns true for (x == null) would also throw a NullReferenceException if you call x.ToString(). – Dan Bryant Mar 15 '10 at 17:25
5

I know, long after it was relevant, but ... I suspect it is because for nullable types like int? the .ToString() method does not allow you to use format strings. See How can I format a nullable DateTime with ToString()? . Perhaps in the original code, there was a format string in .ToString(), or perhaps the coder forgot that .ToString() without the format string was still available on nullable types.

Community
  • 1
  • 1
outis nihil
  • 736
  • 6
  • 16
5

No, you're correct, the shorter version is the same as what other folks have done in that regard. The other construct I tend to use a lot instead of the ternary with nullables is the null coalescing operator,. which also protects you from nulls. For ToString() it's not necessary (as you pointed out) but for default int values (for example) it works nicely, e.g.:

int page = currentPage ?? 1;

that lets you do all the integer operations on page w/o first explicitly null checking and calling for the value in currentPage (where currentPage is an int? perhaps passed as a param)

Paul
  • 35,689
  • 11
  • 93
  • 122
3

Maybe it is just to follow a pattern? Or they don't know the backend. You are right that the code is exactly the same. You can even do:

int? i = null;
i.ToString(); //No NullReferenceException
Pang
  • 9,564
  • 146
  • 81
  • 122
Andrey
  • 59,039
  • 12
  • 119
  • 163
3

int? is syntax sugar which simplifies declaration of nullable variable. It is the same as Nullable<int>.

So if you take a look at the implementation of ToString() method for Nullable<T> (see below), you can notice, that it returns empty string in case if it has no value.

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

What MSDN says:

Nullable.ToString Method

Returns the text representation of the value of the current Nullable object if the HasValue property is true, or an empty string ("") if the HasValue property is false.

So the following code will print empty string to console instead of throwing ArgumentNullException exception.

static void Main(string[] args)
{
    int? a = null;
    Console.WriteLine(a.ToString()); // Prints empty string to console.
}
Aliaksei Maniuk
  • 1,534
  • 2
  • 18
  • 30