如何编译C#字符串插值?
我知道插值是string.Format()
语法糖,但是当它与字符串格式化方法一起使用时,它是否有任何特殊的行为/识别?
如果我有一个方法:
void Print(string format, params object[] parameters)
以下使用插值调用它:
Print($"{foo} {bar}");
以下哪个调用行最相当于字符串插值的编译结果?
Print(string.Format("{0} {1}", new[] { foo, bar })); Print("{0} {1}", new[] { foo, bar });
问题背后的推理:NLog等日志框架通常会延迟字符串格式化,直到确定实际写入日志消息为止。 一般来说,我更喜欢字符串插值语法,但我需要知道它是否会产生额外的性能损失。
它以两种方式之一编译。
如果使用字符串插值表达式,其中需要一个string
,则将其编译为对string.Format
的调用。
基本上,这个:
string s = $"now is {DateTime.Now}";
变成这样:
string s = string.Format("now is {0}", DateTime.Now);
在Try Roslyn中亲眼看看 。
这里没什么神奇的。
现在,另一方面,如果您在一个需要FormattableString
(.NET 4.6中的新类型)的地方使用它,它将被编译为对FormattableStringFactory.Create
的调用:
public void Test(FormattableString s) { } Test($"now is {DateTime.Now}");
那里的电话变成了这个:
Test(FormattableStringFactory.Create("now is {0}", DateTime.Now));
在Try Roslyn中亲眼看看 。
所以从本质上讲,在那里回答你的最后一个问题:
这个电话:
Print($"{foo} {bar}");
将翻译成这个:
Print(string.Format("{0} {1}", foo, bar));
这甚至会在调用Print
之前通过string.Format
产生格式化的代价。
如果您可以添加或查找带有FormattableString
的Print
FormattableString
,那么您可以推迟string.Format
的实际开销,直到您确定是否需要记录为止。 这在运行时是否具有可测量的差异很难说。
在Try Roslyn中亲眼看看 。
奖金回合
不仅延迟了实际格式,而且FormattableString
的ToString
方法允许您指定IFormatProvider
。
这意味着您也可以推迟本地化转换。
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"))); }