Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#是否优化了字符串文本的串联?_C#_.net_Performance_Optimization - Fatal编程技术网

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

C#是否优化了字符串文本的串联?,c#,.net,performance,optimization,C#,.net,Performance,Optimization,例如,编译器知道翻译吗 string s = "test " + "this " + "function"; 到 从而避免字符串串联对性能的影响?是的。这是由C#规范保证的。在C#3.0规范的第7.18节中: 每当表达式满足 以上列出的要求 表达式的计算时间为 编译时。这是真的,即使 表达式是表达式的子表达式 包含 非常量构造 (上述“要求”包括应用于两个常量表达式的+运算符。) 另请参见。我相信答案是肯定的,但您必须查看编译器输出的内容。。。只需编译,并在其上使用reflector:-)是的

例如,编译器知道翻译吗

string s = "test " + "this " + "function";


从而避免字符串串联对性能的影响?

是的。这是由C#规范保证的。在C#3.0规范的第7.18节中:

每当表达式满足 以上列出的要求 表达式的计算时间为 编译时。这是真的,即使 表达式是表达式的子表达式 包含 非常量构造

(上述“要求”包括应用于两个常量表达式的+运算符。)


另请参见。

我相信答案是肯定的,但您必须查看编译器输出的内容。。。只需编译,并在其上使用reflector:-)

是的

C#不仅优化了字符串文字的串联,它还将等效的字符串文字压缩为常量,并使用指针引用同一常量的所有引用。

来自:

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


只是一个相关主题的旁注-C编译器还将使用“
+
”运算符对String.Concat()方法的多参数重载的单个调用“优化”涉及非文本的多个串联

所以

编译成相当于

string result = String.Concat( x, y, z);
而不是更天真的可能性:

string result = String.Concat( String.Concat( x, y), z);

没有什么惊天动地的,只是想在关于字符串文字连接优化的讨论中添加这一点。我不知道这种行为是否受语言标准的约束。

我有一个类似的问题,但是关于VB.NET而不是C#。验证这一点的最简单方法是在Reflector下查看已编译的程序集


答案是C#和VB.NET编译器都优化了字符串文本的串联。

是-您可以使用ILDASM明确地看到这一点

例如:

下面是一个与您的示例类似的程序,后面是编译的CIL代码:

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

节目

class Program
{
    static void Main(string[] args)
    {
        string s = "test " + "this " + "function";
        string ss = String.Concat("test", "this", "function");
    }
}
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

请注意,在IL_0001中,编译器是如何创建常量“testthis function”的,而不是编译器如何处理String.Concat()函数的,后者为每个.Concat()参数创建一个常量,然后调用.Concat()函数。

介意我将问题改为C吗?知道这是否仍然适用于插值字符串吗?我试图理解C#6规范的(草案),但是如果你不习惯阅读这样的文档,这种语言会很混乱:)@Stijn:不,插值字符串文字不是常量表达式。@JonSkeet我知道总体来说它们不是,但是是
$“hello{foo},I'm{bar}”
$“hello{foo}”+$“I'm{bar}”
?@Stijn:不,在第二个例子中,您将分别调用
string.Format
。它被称为“字符串内部调用”,在CLR via C#一书中有详细介绍。
class Program
{
    static void Main(string[] args)
    {
        string s = "test " + "this " + "function";
        string ss = String.Concat("test", "this", "function");
    }
}
.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