Why does Convert.ToString(null) return a different value if you cast null?

There are 2 overloads of ToString that come into play here

Convert.ToString(object o);
Convert.ToString(string s);

The C# compiler essentially tries to pick the most specific overload which will work with the input. A null value is convertible to any reference type. In this case string is more specific than object and hence it will be picked as the winner.

In the null as object you've solidified the type of the expression as object. This means it's no longer compatible with the string overload and the compiler picks the object overload as it's the only compatible one remaining.

The really hairy details of how this tie breaking works is covered in section 7.4.3 of the C# language spec.


Following on from JaredPar's excellent overload resolution answer - the question remains "why does Convert.ToString(string) return null, but Convert.ToString(object) return string.Empty"?

And the answer to that is...because the docs say so:

Convert.ToString(string) returns "the specified string instance; no actual conversion is performed."

Convert.ToString(object) returns "the string representation of value, or String.Empty if value is null."

EDIT: As to whether this is a "bug in the spec", "very bad API design", "why was it specified like this", etc. - I'll take a shot at some rationale for why I don't see it as big deal.

  1. System.Convert has methods for converting every base type to itself. This is strange - since no conversion is needed or possible, so the methods end up just returning the parameter. Convert.ToString(string) behaves the same. I presume these are here for code generation scenarios.
  2. Convert.ToString(object) has 3 choices when passed null. Throw, return null, or return string.Empty. Throwing would be bad - doubly so with the assumption these are used for generated code. Returning null requires your caller do a null check - again, not a great choice in generated code. Returning string.Empty seems a reasonable choice. The rest of System.Convert deals with value types - which have a default value.
  3. It's debatable whether returning null is more "correct", but string.Empty is definitely more usable. Changing Convert.ToString(string) means breaking the "no actual conversion" rule. Since System.Convert is a static utility class, each method can be logically treated as its own. There's very few real world scenarios where this behavior should be "surprising", so let usability win over (possible) correctness.