简体   繁体   中英

How is C# string interpolation compiled?

I know that interpolation is syntactic sugar for string.Format() , but does it have any special behavior/recognition of when it is being used with a string formatting method?

If I have a method:

void Print(string format, params object[] parameters)

And the following call to it using interpolation:

Print($"{foo} {bar}");

Which of the following calls lines is most equivalent to the compiled result of string interpolation?

Print(string.Format("{0} {1}", new[] { foo, bar }));
Print("{0} {1}", new[] { foo, bar });

Reasoning behind the question: Logging frameworks such as NLog typically defer string formatting until they have determined that a log message will actually be written. In general I prefer the string interpolation syntax, but I need to know if it may incur an extra performance penalty.

It is compiled in one of two ways.

If you use a string interpolation expression where a string is expected, it is compiled into a call to string.Format .

Basically, this:

string s = $"now is {DateTime.Now}";

is turned into this:

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

See it for yourself in Try Roslyn .

Nothing magical here.

Now, on the other hand, if you use it in a place where a FormattableString (a new type in .NET 4.6) is expected, it is compiled into a call to FormattableStringFactory.Create :

public void Test(FormattableString s)
{
}

Test($"now is {DateTime.Now}");

The call there is turned into this:

Test(FormattableStringFactory.Create("now is {0}", DateTime.Now));

See it for yourself in Try Roslyn .

So in essence, to answer your final question there:

This call:

Print($"{foo} {bar}");

Will be translated to this:

Print(string.Format("{0} {1}", foo, bar));

which will incur the cost of the formatting through string.Format before Print is even called.

If you could add, or find, an overload of Print that takes a FormattableString , then you could defer the actual cost of string.Format until after you've figured out if you need to log. Whether this has a measurable different in runtime is hard to say.

See it for yourself in Try Roslyn .


Bonus Round

Not only is the actual formatting deferred, but the ToString method of FormattableString allows you to specify a IFormatProvider .

This means that you can defer localized transformation as well.

public static void Print(FormattableString s)
{
    Console.WriteLine("norwegian: " + s.ToString(CultureInfo.GetCultureInfo("nb-NO")));
    Console.WriteLine("us: " + s.ToString(CultureInfo.GetCultureInfo("en-US")));
    Console.WriteLine("swedish: " + s.ToString(CultureInfo.GetCultureInfo("sv-SE")));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM