【问题标题】:How smart is the compiler at optimizing string concatenation.编译器在优化字符串连接方面有多聪明。
【发布时间】:2013-06-23 17:23:34
【问题描述】:

我很好奇 C# 编译器会如何处理下面的两个语句:

String text = "abcdefghijklmnopqrstuvwxyz";
text = text.Substring( 0, 15 );
text = text + "...";

对比

String text = "abcdefghijklmnopqrstuvwxyz";
text = text.Substring( 0, 15 ) + "...";

结果当然是一样的,但是在第二次设置中,连接操作符是否更好地优化了代码?

在这两种情况下,您最终会为堆栈上的字符串分配 4 次,还是第二种情况只分配 3 次?

只是我在阅读一些代码时遇到的一个随机问题。

【问题讨论】:

  • 否;它们完全相同。
  • 如果您想了解有关字符串连接的更多信息,Eric Lippert 刚刚在他的博客 String concatenation behind the scenes, part onetwo 上开始了一个新系列
  • 据我所知,与+ 运算符的字符串连接被转换为string.Concat() 调用。如果你有很多,只需使用StringBuilder 类。

标签: c# .net clr compiler-optimization string-concatenation


【解决方案1】:

首先,字符串不是首先分配在堆栈上的。字符串在堆上。

其次,在这两种情况下都有四个分配。我很好奇你认为哪一个会消失。

巧合的是,这是我本周博客的主题。请参阅this article,了解有关此主题的更多信息。

【讨论】:

  • 我只是想知道在不单独分配子字符串的情况下将文字与子字符串连接起来是否足够聪明。这似乎有些牵强,但我很好奇。
  • @HunterLewis Substring 是一个返回 string 的方法。我能看到避免分配 string 的唯一方法是 C# 编译器以某种方式内联 Substring() 方法。这是您的预期吗?
  • 这已经足够接近我的想法了。我想得越多,它就越没有意义。 :)
【解决方案2】:

我获取了您的代码并将其编译到一个简单的控制台应用程序中。然后,我检查了 IL(使用 ILSpy)。在 Debug 或 Release 模式下均未进行任何优化。

在这种情况下,代码可能足够简单,编译器没有进行任何优化。但是,更复杂的版本可能会产生不同的结果。

另外,请注意,这两个示例之间几乎没有区别。在这两种情况下,运行时最终都会生成四个不同的字符串对象。在第一个示例中,对变量的赋值只进行了两次,而在第二个示例中,赋值进行了三次。但是,无论如何都会创建四个字符串。它们如下:

  • "abcdefghijklmnopqrstuvwxyz"
  • “abcdefghijklmno”(来自子字符串)
  • “...”
  • “abcdefghijklmno...”(来自串联)

在这两种情况下,前三个字符串几乎都可以立即进行垃圾回收。我猜编译器没有看到任何重要的方法来改进你所拥有的。

【讨论】:

  • 默认情况下,文字字符串被保留,因此它们可能不会被迅速收集。如果 GC 对实习字符串的攻击性较小,我不知道其中一种方法,但这似乎是合理的。
  • 公平。更准确地说,为这些字符串创建的对象符合垃圾回收条件。第一个和第三个字符串将保留在字符串实习生池中,尽管它们只有在我们再次使用确切的文字字符串时才有价值。好收获!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-22
  • 1970-01-01
  • 2021-02-18
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
相关资源
最近更新 更多