C#字符串插值是如何编译的? [英] How is C# string interpolation compiled?

查看:43
本文介绍了C#字符串插值是如何编译的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道插值是 string.Format() 的语法糖,但是当它与字符串格式化方法一起使用时,它是否有任何特殊的行为/识别?

如果我有一个方法:

void Print(字符串格式,params object[] 参数)

以下使用插值调用它:

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

以下哪一行调用最符合字符串插值的编译结果?

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

问题背后的原因:NLog 等日志记录框架通常会推迟字符串格式化,直到它们确定实际写入日志消息.一般来说,我更喜欢字符串插值语法,但我需要知道它是否会导致额外的性能损失.

解决方案

它以两种方式之一编译.

如果您在需要 string 的地方使用字符串插值表达式,则会将其编译为对 string.Format 的调用.

基本上,这个:

string s = $"现在是{DateTime.Now}";

变成这样:

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

FormattableStringFactory.Create:

public void Test(FormattableString s){}Test($"现在是{DateTime.Now}");

那里的电话变成了这样:

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

查看它自己在尝试罗斯林.

所以本质上,在那里回答你的最后一个问题:

这个电话:

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

将被翻译成这样:

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

这将在调用 Print 之前通过 string.Format 产生格式化成本.

如果您可以添加或找到采用 FormattableStringPrint 重载,那么您可以推迟 string.Format 的实际成本代码> 直到您确定是否需要登录.这在运行时是否有可衡量的差异很难说.

查看它自己在尝试罗斯林.

<小时>

奖金回合

不仅延迟了实际的格式设置,而且FormattableStringToString 方法允许您指定一个IFormatProvider.

这意味着您也可以推迟本地化转换.

public static void Print(FormattableString s){Console.WriteLine("挪威语:" + s.ToString(CultureInfo.GetCultureInfo("nb-NO")));Console.WriteLine("我们:" + s.ToString(CultureInfo.GetCultureInfo("en-US")));Console.WriteLine("瑞典语:" + s.ToString(CultureInfo.GetCultureInfo("sv-SE")));}

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")));
}

这篇关于C#字符串插值是如何编译的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆