11

I have foo (object) and foo2 (string) in a C# console application. The Code 2 throws exception while Code 1 works fine.

Can you please explain why it is behaving so (with MSDN reference)?

// Code 1

object foo = null;
string test = Convert.ToString(foo).Substring(0, Convert.ToString(foo).Length >= 5 ? 5 : Convert.ToString(foo).Length);

// Code 2

string foo2 = null;
string test2 = Convert.ToString(foo2).Substring(0, Convert.ToString(foo2).Length >= 5 ? 5 : Convert.ToString(foo2).Length);
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
LCJ
  • 22,196
  • 67
  • 260
  • 418
  • 2
    _"Can you please explain why it is behaving so (with MSDN reference)?"_ - [I just did that on your previous question](http://stackoverflow.com/questions/13513961/method-call-on-null-object-does-not-throw-exception/13514155#comment18498922_13514155). – CodeCaster Nov 22 '12 at 14:06
  • @CodeCaster I am sorry. I was not able to understand that from your explanation. – LCJ Nov 22 '12 at 14:12
  • No problem, you could've commented on my comment, but now you've got your answer anyway. ;-) – CodeCaster Nov 22 '12 at 14:15

3 Answers3

34

From the documentation of Convert.ToString(string):

Return Value
Type: System.String
value is returned unchanged.

So null input will result in a null return value.

From the documentation of Convert.ToString(object):

Return Value
Type: System.String
The string representation of value, or String.Empty if value is null.

(Where "Nothing" means "null" here.)

So null input will result in an empty string (non-null reference) return value.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @Lijo: Yes, these are in fact two different methods, not one that behaves differently. Methods in the same type (e.g. class) having the same name but different parameter lists are said to be overloaded. See [Member Overloading](http://msdn.microsoft.com/en-us/library/ms229029(v=vs.80).aspx). – Olivier Jacot-Descombes Nov 22 '12 at 14:29
  • 1
    `..or String.Empty if value is Nothing.` is replaced by `..or String.Empty if value is null.` by the way `:)` – Soner Gönül Jan 14 '14 at 07:25
  • 2
    @SonerGönül: Thanks - looks like MSDN is now context-sensitive not just for the code snippet, but also that sort of documentation. Interesting. – Jon Skeet Jan 14 '14 at 07:29
  • 3
    Thanks... but this is somewhat strange. – JobaDiniz Feb 08 '17 at 11:40
5

Because:

This is implementation of Convert.ToString(object value)

public static string ToString(Object value) {
    return ToString(value,null);
}

public static string ToString(Object value, IFormatProvider provider) { 
    IConvertible ic = value as IConvertible; 
    if (ic != null)
        return ic.ToString(provider); 
    IFormattable formattable = value as IFormattable;
    if (formattable != null)
        return formattable.ToString(null, provider);
    return value == null? String.Empty: value.ToString(); 
}

and this is of Convert.ToString(string value)

public static String ToString(String value) {
        Contract.Ensures(Contract.Result<string>() == value);  // We were always skipping the null check here.
        return value; 
    }
Hamlet Hakobyan
  • 32,965
  • 6
  • 52
  • 68
-1

From this Link:

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.

Community
  • 1
  • 1
KF2
  • 9,887
  • 8
  • 44
  • 77