C# 使用常量的字符串Concat-性能

C# 使用常量的字符串Concat-性能,c#,performance,memory,string,stringbuilder,C#,Performance,Memory,String,Stringbuilder,假设我有以下字符串常量: 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: 备选案文2: string resultString

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

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:

备选案文2:

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

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

第一个将由编译器完成(至少是Microsoft C#编译器)(与编译器执行1+2的方式相同),第二个必须在运行时完成。很明显,第一个更快

作为一个额外的好处,在第一个例子中字符串是内部化的,而在第二个例子中它不是

和String.Format非常慢:-)(请阅读此
)除非你的程序整天都在格式化字符串(数以百万计,而不是几十个),否则不要“慢到足以成为一个问题”。然后,您可能可以更快地将它们附加到
StringBuilder
中,第一个变量将是最好的,但仅当您使用常量字符串时。

有两种编译器优化(来自C#编译器,而不是JIT编译器)在这里有效。让我们举一个程序的例子

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

...
string test = A + B;
第一个优化是不断传播,它将基本上将您的代码更改为:

string test = "Hello " + "World";
然后,文字字符串的串联(由于第一次优化,现在是这样)优化将启动并将其更改为

string test = "Hello World";

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

这有点过早优化的味道。可能重复@nathan-以及尝试在不测量的情况下优化…。@System.Exception否,不同的问题。在这里,他要的是常量字符串的concat。“副作用”(编译器如何优化它)非常有趣,一个新问题就可以解决了。结果(CONTAT比格式快)是相同的,但是还有另外一个原因。@ XANATOS:在这种情况下,为什么CONTAT应该比格式化快(没有任何技术原因,包括格式字符串),没有任何技术原因。即使是C++编译器也可以将这两个字符串优化为相同的指令,CLR JIT将它们合并到相同的程序集应该没有问题。当然,它可能不会真的这样做,但不是因为缺乏信息。唯一确定的方法是测试它。实际上,这里提到的优化是由C#编译器完成的,而不是由JIT编译器完成的。当然,我的观点是,即使CLR编译器没有这样做(显然可以,因为编译时您有足够的信息),它当然可以在运行时轻松地完成它。@Øyfind是的。我已经用反射器检查过了,我正在改正。我对在这里实习的绳子不太确定。我运行了一个测试,表明字符串也被
string.Format
场景所替代(我发现这有点令人惊讶);对于非文本,它仍然将编译为单个
string.Concat
call,不需要解析格式字符串(
“{0}{1}{2}{3}”
string test = "Hello World";