百科问答小站 logo
百科问答小站 font logo



C#中的String.Format()这两种写法那个更好? 第1页

  

user avatar   rednaxelafx 网友的相关建议: 
      

这是个老话题了。

如果不想依赖CLR(或其它CLI VES的实现)中的优化的话,对于 int a; ,是 String.Format("a = {0}", a.ToString()) 比 String.Format("a = {0}", a) 的开销更小。

String.Format()有若干个重载版本,其中题主的例子会用到的是:

String.Format Method (String, Object)
       public static string Format(  string format,  object arg0 )      

所以如果直接传入a的话,int -> object需要做一次自动装箱(auto boxing),然后在 String.Format(string, object) 的内部实现里会再对这个object参数调用其ToString()方法来获得需要拼接的内容的String表示。

而如果传入a.ToString()的话,a.ToString()这个调用自身并不会导致装箱,得到的String传给String.Format()正好跟object匹配,就避免了一次额外的装箱操作。

具体到System.String在CoreCLR中的实现,String.Format(string, object) 的实现在

github.com/dotnet/corec

,它内部经过几层调用真正实现逻辑的地方在

github.com/dotnet/corec

,可以看到真正调用 arg.ToString() 的地方离 String.Format(string, object) 还隔着好几层,以CoreCLR的JIT(RyuJIT)的优化能力来说很难充分优化,于是就很难靠JIT优化自动消除 String.Format("a = {0}", a) 形式的代码导致的自动装箱。

但这个装箱的开销很大么?是否要教条式避免?

我个人是觉得这种地方显式调用ToString()是个好习惯,不会让代码丑很多而且可以自然地避免一些性能坑。

但同时我也不觉得这个地方的开销会很大,如果不调用ToString()真的导致很严重的问题的话profile的时候肯定会看到,看到的时候再改就是了。所以我完全不介意别人的习惯是在这种地方不显式调用ToString()。

有同学说这里调用a.ToString()可能会遇到NullReferenceException <- 请看清楚问题。题主的问题是假设a是int,是一个value type的情况下,是否应该显式调用a.ToString()再传给String.Format()。针对value type的方法调用是永远不会NRE的。

也有同学提到C# 6的新功能,interpolated strings。这当然是个好功能,我也很喜欢。这个功能的规范提到,当一个interpolated string被用在string类型的上下文中,它的语义等价于调用String.Format()。

请看Roslyn是如何翻译下面代码的:

Try Roslyn
       public class Test {     public string M(int a) {         return $"a = {a}";     } }      

会被目前的Roslyn翻译为等价于:

       public class Test {     public string M(int a)     {         return string.Format("a = {0}", a); // autobox a     } }      

也就是说C#的interpolated strings在当前Roslyn中的实现不会在调用String.Format()前自动给value type插入ToString()调用。这也是个很合理的设计——毕竟语言规范要尽可能简明扼要,把一个语法糖的解糖形式设计得简单也是好的。




  

相关话题

  你遇到过哪些代码优雅的C#项目? 
  C# 中如何在不使用 async和await 关键字的情况下构建一个按照顺序执行的 Task 集合? 
  c#中没有友元类那么这种设计是否不太合理,如何修改才能得到更好的方案? 
  微软开源了 Core CLR,作为 .NET 开发人员,是否需要花精力去研究Core CLR 源代码?为什么? 
  有没有什么工具可以帮助理解源代码的? 
  关于C#泛型枚举器的问题? 
  同事离职,我接盘了个垃圾项目,该如何是好? 
  Build 2015上微软宣布Windows 10支持Objective-C与Java编写的应用,这对C#与Windows自身有什么长远影响? 
  ASP.NET MVC 如果全部用异步 Controller,会有什么效果?会成为高吞吐量,高并发的网站么? 
  微软开放.net框架源代码后,未来的发展有哪些可期待的? 

前一个讨论
bad apple怎么入侵广场上的led屏幕里的?
下一个讨论
千古帝王和牛顿、爱迪生、特斯拉这样的人对人类福祉影响谁更大?





© 2025-04-25 - tinynew.org. All Rights Reserved.
© 2025-04-25 - tinynew.org. 保留所有权利