使用常量进行字符串拼接 - 性能问题

4

假设我有以下字符串常量:

const string constString1 = "Const String 1";
const string constString2 = "Const String 2";
const string constString3 = "Const String 3";
const string constString4 = "Const String 4";

现在我可以用两种方式连接字符串: 选项1:

string resultString = constString1 + constString2 + constString3 + constString4;

选项2:

string resultString = string.Format("{0}{1}{2}{3}",constString1,constString2,constString3,constString4);

在内部,string.Format使用StringBuilder.AppendFormat。现在考虑到我正在附加常量字符串,哪个选项(选项1或选项2)在性能和/或内存方面更好?

在这种情况下,选项1更好。因为它只需要在编译时分配一次内存,而选项2需要在运行时分配多次内存。

7
这听起来像过早的优化。 - nathan gonzalez
可能是重复的问题 https://dev59.com/nnVC5IYBdhLWcg3wbghT - Numan
1
@nathan - 而且试图在没有测量的情况下进行优化... - Marc Gravell
1
@xanatos:在这种情况下,concat应该比format更快没有技术上的原因(所有字符串都是常量,包括格式化字符串)。 - Nick Bastin
@xanatos:我认为,我同意Nick Bastin的观点。你能具体说明一下你在这两个方面的发现,并且你是基于什么来得出哪一个更快的结论的吗? - Numan
显示剩余3条评论
2个回答

11

第一个操作会在编译时完成(至少是Microsoft C#编译器),类似于编译器执行1 + 2的方式,第二个操作必须在运行时完成。因此,很明显第一个操作更快。

额外的好处是,在第一个操作中,字符串被内部化(interned),而在第二个操作中没有。

而String.Format相当慢 :-)(请参阅http://msmvps.com/blogs/jon_skeet/archive/2008/10/06/formatting-strings.aspx)。除非你的程序一整天都只做格式化字符串(成千上万次,而不是几十次),否则它并不“足够慢以至于成为问题”。那么你可能可以通过将它们附加到StringBuilder来更快地完成这些操作。


即使是C++编译器也可以将它们优化为相同的指令,CLR JIT应该没有问题将它们合并到相同的程序集中。当然,它可能实际上并不这样做,但并不是因为缺乏信息。唯一确定的方法是进行测试。 - Nick Bastin
实际上,你在这里提到的优化是由C#编译器而不是JIT编译器完成的。 - Øyvind Bråthen
当然,我的观点是,即使CLR编译器没有这样做(显然它可以,因为在编译时你有足够的信息),它肯定可以在运行时轻松地完成。 - Nick Bastin
@Øyvind 是的,我已经用 Reflector 检查过了,正在进行修正。 - xanatos
我对字符串内部化并不十分确定。我进行了一项测试,表明字符串也通过string.Format场景进行了内部化(这让我感到有些惊讶)。 - Fredrik Mörk
显示剩余2条评论

0

第一种变体是最好的,但仅适用于使用常量字符串的情况。

这里有两个编译器优化(来自C#编译器,而不是JIT编译器)正在生效。让我们以一个程序为例。

const string A = "Hello ";
const string B = "World";

...
string test = A + B;

首先进行的优化是常量传播,它会将您的代码基本上更改为以下内容:

string test = "Hello " + "World";

然后,由于第一个优化,对文字串(因为它们现在是)的连接进行了优化,将其更改为

string test = "Hello World";

所以,如果您编写上述程序的任何变体,由于C#编译器进行的优化,实际的IL将是相同的(或者至少非常相似)。


4
不管怎样,第一个版本都是最好的;即使使用非文字字面量,它仍将编译为单个 string.Concat 调用,并且不需要解析格式字符串("{0}{1}{2}{3}")。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接