【问题标题】:C# string concatenation - in-line vs. line-by-lineC# 字符串连接 - 内联与逐行
【发布时间】:2011-10-26 16:53:08
【问题描述】:

C#代码:

string first = "A"; 
first += "B"; 
first += "C";
string second = "D" + "E" + "F";


生成的 IL 代码:

.locals init ([0] string first,
           [1] string second)
  IL_0000:  nop
  IL_0001:  ldstr      "A"
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldstr      "B"
  IL_000d:  call       string [mscorlib]System.String::Concat(string,
                                                              string)
  IL_0012:  stloc.0
  IL_0013:  ldloc.0
  IL_0014:  ldstr      "C"
  IL_0019:  call       string [mscorlib]System.String::Concat(string,
                                                              string)
  IL_001e:  stloc.0
  IL_001f:  ldstr      "DEF"
  IL_0024:  stloc.1
  IL_0025:  ret

很明显,内联连接效率更高一些,因为它只调用了一次 ldstr,但还有其他区别(例如在内存中创建的字符串对象?)

谢谢

【问题讨论】:

  • 它也从不调用String.Concat()
  • 关于主题codinghorror.com/blog/2009/01/…的有用阅读
  • 这绝对是因为编译器意识到“D”、“E”和“F”是常量,可以在编译时而不是在运行时一起滚动。
  • @JesseC.Slicer 是的,在每种情况下都将const 放在string 之前并查看编译器错误会很快显示这一点; “D”+“E”+“F”是一个常量表达式。不过,还有更多值得研究的地方。

标签: c# string


【解决方案1】:
string second = "D" + "E" + "F"; 

优化为:

string second = "DEF";

【讨论】:

    【解决方案2】:

    是的,正如你所说 - 在内存中创建的字符串对象。

    尝试手动将 IL 转回 C#。代码几乎等同于:

    string first = "A";
    string __temp = "B";
    first = string.Concat(first, __temp);
    __temp = "C";
    first = string.Concat(first, __temp);
    
    second = "DEF";
    

    未来还有更多优势。因为它是以下字符串将在实习生池中:“A”、“B”、“C”、“DEF”。这里更有利的是取决于几件事,但可能最好使用池中实际使用的字符串,并且除了创建“ABC”之外不使用“A”、“B”和“C” .但在实际代码中,这些子字符串可能会更重要。

    不过,最重要的是,请注意,这不是直插式与逐行式之间的公平比较。请尝试以下操作:

    using(TextReader tr = new StreamReader(someFile))//no way for compiler to know what this will contain
    {
      string a = tr.ReadLine();
      string b = tr.ReadLine();
      string c = tr.ReadLine();
      string d = tr.ReadLine();
      string e = tr.ReadLine();
      string f = tr.ReadLine();
      string first = a;
      first += b;
      first += c;
      string second = d + e + f;
    }
    

    因为字符串不是硬编码的文字,可用的优化是不同的,所以两者之间的比较会有所不同。但在其他情况下会出现更多差异。

    【讨论】:

    • 对于那些有悬念的人:逐行调用看起来几乎相同(每个都有一个String.Concat()),而内联方法将只有一个@ 987654325@电话。 msdn.microsoft.com/en-us/library/0wkb0y3w.aspx
    • 是的,这使得第二个仍然击败第一个,虽然不是那么多。
    【解决方案3】:

    在逐行的情况下,编译器没有进行优化以注意到line 的值在编译时的每一点都可以知道。在单行的情况下,它确实有这种优化。

    我怀疑只有 C# 编译器团队的成员才能确定地告诉您为什么他们没有优化第一种情况,尽管我怀疑这是由于分析多行代码的相对复杂性与 C# 程序员的相对收益相比。

    【讨论】:

    • 通过在每个字符串声明之前放置const,很容易看出前者不如后者优化的原因。第二个是允许的,因为它是一个常量表达式,而不是第一个。这并不是说编译器不能同时优化第一个,但我们会更惊讶地发现第二个不是,因为常量表达式通常是。
    【解决方案4】:

    对于常量,它是C# Compile-Time Concatenation For String Constants 的副本(合并字符串常量)。

    否则使用 StringBuilder 并感到高兴。

    【讨论】:

      猜你喜欢
      • 2021-07-08
      • 2016-10-13
      • 1970-01-01
      • 2017-07-22
      • 2012-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-13
      相关资源
      最近更新 更多