C#字符串插值是如何编译的? [英] How is C# string interpolation compiled?
问题描述
我知道插值是 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
产生格式化成本.
如果您可以添加或找到采用 FormattableString
的 Print
重载,那么您可以推迟 string.Format
的实际成本代码> 直到您确定是否需要登录.这在运行时是否有可衡量的差异很难说.
奖金回合
不仅延迟了实际的格式设置,而且FormattableString
的ToString
方法允许您指定一个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屋!