What is the original type of interpolated string?

The new interpolated string syntax is part compiler magic and part runtime classes.

Let’s go through all the scenarios and see what is actually happening.

  1. var s = $"{DateTime.Now}";

    This gets compiled as this:

    string s = string.Format("{0}", DateTime.Now);
    

    See Try Roslyn for details.

  2. string s = $"{DateTime.Now}";

    This gets compiled as this:

    string s = string.Format("{0}", DateTime.Now);
    

    See Try Roslyn for details.

  3. object s = $"{DateTime.Now}";

    This gets compiled as this:

    object s = string.Format("{0}", DateTime.Now);
    

    See Try Roslyn for details.

  4. IFormattable s = $"{DateTime.Now}";

    This gets compiled as this:

    IFormattable s = FormattableStringFactory.Create("{0}", new object[] {
        DateTime.Now
    });
    

    See Try Roslyn for details.

  5. FormattableString s = $"{DateTime.Now}";

    This gets compiled as this:

    FormattableString s = FormattableStringFactory.Create("{0}", new object[] {
        DateTime.Now
    });
    

    See Try Roslyn for details.

So we can summarize the compiler magic as follows:

  1. If we can get by with just using string, created with a call to String.Format, then do that
  2. If not, use FormattableString, and create one via FormattableStringFactory.Create

Since we do not yet have an officiel C# 6 standards document, other than perusing the github repositories, issues, and discussions, the exact rules for this is not known (at least not to me, please prove me wrong!).

So, the above examples shows what happens if the compiler knows the target type, in this case through the variable type. If we call a single method, with no overloads, that has one of those types, the exact same “magic” will happen.

But what happens if we have overloads?

Consider this example:

using System;

public class Program
{
    public static void Main()
    {
        Test($"{DateTime.Now}");
    }

    public static void Test(object o) { Console.WriteLine("object"); }
    public static void Test(string o) { Console.WriteLine("string"); }
    public static void Test(IFormattable o) { Console.WriteLine("IFormattable"); }
    // public static void Test(FormattableString o) { Console.WriteLine("FormattableString"); }
}

When executing this example we get this output:

string

So clearly string is still preferred, even when multiple options are available.

See this .NET fiddle for details.

Note that .NET Fiddle for some reason does not allow me to use FormattableString directly, but if I run the same code, with that overload present, in LINQPad, I still get string as the output.

If I then remove the string overload I get FormattableString, and then if I remove that I get IFormattable, so with overloads I can then observe that the rules are, and here we stop with the first overload that has:

  1. string
  2. FormattableString
  3. IFormattable
  4. object

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)