4

Is there any difference between these two approaches?

static void Main(string[] args)
{
    object str = null;

    string test1 = str?.ToString() ?? "";

    string test2 = Convert.ToString(str);
}

Edit 1:

As @Fabio pointed out, we have a third possible approach:

string test3 = $"{str}";
Marco Salerno
  • 5,131
  • 2
  • 12
  • 32
  • 1
    Another similar case, but without null coalescing operator: https://stackoverflow.com/questions/2828154/difference-between-convert-tostring-and-tostring. – Tetsuya Yamamoto Nov 26 '18 at 08:51
  • 1
    You can start reading from [here](https://github.com/Microsoft/referencesource/blob/master/mscorlib/system/convert.cs#L1801) if you want to know the implementation specifics. – ProgrammingLlama Nov 26 '18 at 08:51
  • 1
    Here are two links from reference source: **[Convert.ToString(Object object)](https://referencesource.microsoft.com/#mscorlib/system/convert.cs,6a1a2c3ac58e60dd)** and **[Object.ToString()](https://referencesource.microsoft.com/#mscorlib/system/object.cs,ff31a6bf27c58f89)** – SᴇM Nov 26 '18 at 08:56
  • 1
    Another approach: `var test3 = $"{str}"` – Fabio Nov 26 '18 at 08:58
  • `var test3 = $"{str}"` will call `string.Format(str)` in the "background", which you can call explicitly as well ;) – Fabio Nov 26 '18 at 09:04

3 Answers3

3

So, to answer your question directly: there is no difference between any of the approaches. There would be a difference in case of an IFormatProvider overload.

Now to dwelve into details:

Convert.ToString will try to call IConvertible and IFormattable interfaces (in that order) before falling back to base object.ToString. So if you pass something that does not implement any of these interfaces (or null on which you can't call any member methods), there will be no difference betweent this and a simple object.ToString.

Now string interpolation is a case of composite formatting (string interpolation is actually equivalent to calling string.Format). This one will call only the IFormattable interface implementation before falling back to object.ToString. Again, in case of something not implementing the interface (or a null), no difference.

To make things more complicated, both of these methods contain an overload that takes an IFormatProvider argument. In case of Convert.ToString the method will try to call IConvertible.ToString(IFormatProvider), if the object implements the IConvertible interface. Then it tries the IFormattable.ToString(String, IFormatProvider) and if that fails it falls back to object.ToString().

In case of composite formatting, it will try to call the IFormatProvider.GetFormat method and then use the returned ICustomFormatter. If that fails it continues to IFormattable and ultimately falls back to object.ToString.

When it comes to null values, there can be a difference when using the IFormatProvider. Since Convert.ToString tries to call the IConvertible implementation, and you can't really call anything on a null, it treats null as a special case and returns string.Empty. However, composite formatting calls the ICustomFormatter.Format with the object as an argument, so if you use an ICustomFormatter that handles null differently, you can get a different result! You can verify it with this code snippet (disclaimer: not the smartest way to implement an IFormatProvider, but it works as an example).

Here's the MSDN doc for Convert.ToString.

Here's the MSDN doc for composite formatting (see the Processing Order section).

V0ldek
  • 9,623
  • 1
  • 26
  • 57
0

If we use Convert.ToString then it can handle the null values.But Tostring cannot handle null values

for example:

object str=null;
System.out.print(convert.ToString(str)); //shows null value
String s=str.ToString();
System.out.print(s); //throws exception
nikhil kumar
  • 55
  • 1
  • 10
0

Convert.ToString tries to use IFormattable and IConvertible interfaces before calling base Object.ToString Example

class FormattableType : IFormattable
{
    private double value = 0.42;

    public string ToString(string format, IFormatProvider formatProvider)
    {
        if (formatProvider == null)
        {
            // ... using some IOC-containers
            // ... or using CultureInfo.CurrentCulture / Thread.CurrentThread.CurrentCulture
            formatProvider = CultureInfo.InvariantCulture;
        }

        // ... doing things with format
        return value.ToString(formatProvider);
    }

    public override string ToString()
    {
        return value.ToString();
    }
}

Result:

Convert.ToString(new FormattableType()); // 0.42
new FormattableType().ToString();        // 0,42
Serhat Oz
  • 788
  • 8
  • 12