C#是否优化了字符串文字的串联?

Lar*_*nal 46 .net c# optimization performance

例如,编译器是否知道要翻译

string s = "test " + "this " + "function";
Run Code Online (Sandbox Code Playgroud)

string s = "test this function";
Run Code Online (Sandbox Code Playgroud)

从而避免字符串连接的性能损失?

Jon*_*eet 50

是.这是由C#规范保证的.它在7.18节(C#3.0规范)中:

只要表达式满足上面列出的要求,就会在编译时计算表达式.即使表达式是包含非常量构造的较大表达式的子表达式,也是如此.

("上面列出的要求"包括应用于两个常量表达式的+运算符.)

另见这个问题.

  • 知道这是否仍然适用于插值字符串吗?我正在尝试理解 C# 6 规范(草案),但如果您不习惯阅读此类文档,那么该语言会非常令人困惑:) (2认同)
  • @Stijn:不,内插字符串文字不是常量表达式。 (2认同)
  • @Stijn:不,在第二个中,您最终会单独调用“string.Format”。 (2认同)

Mic*_*urr 21

只是关于相关主题的附注 - C#编译器还将使用' +'运算符'优化'涉及非文字的多个连接,以单次调用String.Concat()方法的多参数重载.

所以

string result = x + y + z;
Run Code Online (Sandbox Code Playgroud)

编译成等价的东西

string result = String.Concat( x, y, z);
Run Code Online (Sandbox Code Playgroud)

而不是更天真的可能性:

string result = String.Concat( String.Concat( x, y), z);
Run Code Online (Sandbox Code Playgroud)

没有什么是惊天动地的,但只想将这一点添加到关于字符串文字级联优化的讨论中.我不知道这种行为是否是语言标准规定的.


Fly*_*wat 7

是.

C#不仅优化了字符串文字的连接,还将等效的字符串文字折叠为常量,并使用指针引用对同一常量的所有引用.

  • 它被称为“字符串实习”,并在 CLR 一书中通过 C# 进行了深入介绍。 (2认同)

Kev*_*Kev 6

从马嘴里说:

连接是将一个字符串附加到另一个字符串末尾的过程。当您使用 + 运算符连接字符串文字或字符串常量时,编译器会创建单个字符串。不会发生运行时串联。但是,字符串变量只能在运行时连接。在这种情况下,您应该了解各种方法对性能的影响。

http://msdn.microsoft.com/en-us/library/ms228504.aspx


Jed*_*Jed 5

是的 - 您可以使用ILDASM显式地看到这一点.

例:

这是一个类似于您的示例后跟编译的CIL代码的程序:

注意:我正在使用String.Concat()函数来查看编译器如何处理两种不同的连接方法.

程序

class Program
{
    static void Main(string[] args)
    {
        string s = "test " + "this " + "function";
        string ss = String.Concat("test", "this", "function");
    }
}
Run Code Online (Sandbox Code Playgroud)

ILDASM

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       29 (0x1d)
  .maxstack  3
  .locals init (string V_0,
           string V_1)
  IL_0000:  nop
  IL_0001:  ldstr      "test this function"
  IL_0006:  stloc.0
  IL_0007:  ldstr      "test"
  IL_000c:  ldstr      "this"
  IL_0011:  ldstr      "function"
  IL_0016:  call       string [mscorlib]System.String::Concat(string,
                                                              string,
                                                              string)
  IL_001b:  stloc.1
  IL_001c:  ret
} // end of method Program::Main
Run Code Online (Sandbox Code Playgroud)

注意编译器在IL_0001创建常量"测试此函数"而不是编译器如何处理String.Concat()函数 - 它为每个.Concat()参数创建一个常量,然后调用.Concat()功能.