我知道插值是 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);txAFwKYFsDcAoADsAIwBswBj
这里没有什么神奇之处.
现在,另一方面,如果您在需要 FormattableString(.NET 4.6 中的新类型)的地方使用它,它会被编译成对 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 RoundNot 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#字符串插值是如何编译的?
发布评论