【问题标题】:C# + operator calls string.concat function? [duplicate]C# + 运算符调用 string.concat 函数? [复制]
【发布时间】:2012-11-29 02:04:58
【问题描述】:

可能重复:
Does C# optimize the concatenation of string literals?

我刚刚发现我们写了这样一行:

string s = "string";
s = s + s; // this translates to s = string.concat("string", "string");

但是我通过反射器打开了字符串类,我没有看到这个 + 运算符在哪里重载?我可以看到 == 和 != 被重载了。

[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
    public static bool operator ==(string a, string b)
    {
      return string.Equals(a, b);
    }
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
    public static bool operator !=(string a, string b)
    {
      return !string.Equals(a, b);
    }

那么当我们使用 + 组合字符串时,为什么会调用 concat 呢?

谢谢。

【问题讨论】:

  • @MichaelPetrotta 这不是那个问题的重复。链接的问题实际上涉及常量折叠。
  • @phoog,好吧,我有点同意你的观点,因为问题没有涵盖这一点,但 Jon 的回答准确地回答了 VVV 的问题。
  • @MichaelPetrotta,J. Skeet 的回答如何回答这个问题?
  • 如果两个字符串被键入为dynamic,运行时是否硬编码将添加处理为String.Concat
  • @MichaelPetrotta 抱歉,我一直不清楚。我试图强调一个事实,即当前问题的答案是“第 7.7.4 节”,但乔恩对假定重复问题的回答是“第 7.18 节”。 Jon 的回答和问题是关于常量折叠,而不是 + 运算符的定义。这个问题是关于 + 运算符的定义。事实上,这两个问题的共同答案是“编译器会这样做”,但如果我们在规范中寻找“为什么”问题的答案,那么答案就会不同,而且问题不会重复。

标签: c# string operator-overloading concatenation


【解决方案1】:

那么为什么当我们使用 + 组合字符串时会调用 concat 呢?

C# 规范的第 7.7.4 节“加法运算符”定义了字符串的二进制加法运算符,其中运算符返回操作数的串联。

CLI 规范中System.String 的定义包括几个Concat 重载,但没有+ 运算符。 (我没有明确的答案来解释这种遗漏,但我想这是因为某些语言定义了 + 以外的运算符用于字符串连接。)

鉴于这两个事实,C# 编译器编写者最合乎逻辑的解决方案是在编译 +(string, string) 运算符时发出对 String.Concat 的调用。

【讨论】:

  • +1:所有信息...希望有人能提供更多关于这个问题的事实
  • @KonstantinVasilcov 我记得在这个问题上阅读了一些 Eric Lippert 材料;我不记得它是在这里还是在他的博客上,而且我花了太多时间沉迷于规范,现在才开始搜索。但我强烈建议你自己看看。即使你没有找到你要找的东西,你也一定会找到好东西。 blogs.msdn.com/b/ericlippertstackoverflow.com/users/88656/eric-lippert
  • 谢谢!我确实读过 Eric Lippert 的博客))但是不够快)
【解决方案2】:

代码

    public string Foo(string str1, string str2)
    {
        return str1 + str2;
    }

给出以下 IL:

IL_0000:  nop
IL_0001:  ldarg.1
IL_0002:  ldarg.2
IL_0003:  call       string [mscorlib]System.String::Concat(string, string)
IL_0008:  stloc.0
IL_0009:  br.s       IL_000b
IL_000b:  ldloc.0
IL_000c:  ret

编译器(至少是 Visual Studio 2010 中的编译器)完成这项工作,并且没有 + 重载。

【讨论】:

  • 这个答案仅仅证实了 OP 所询问的行为;它没有回答“为什么要这样做?”的问题。
  • @phoog 正如您在其中一条评论中所说的那样。编译器必须以某种方式实现强制转换,因为 + 运算符没有重载。 Visual Studio 编译器使用string.Concat。为什么string.Concat 而不是另一个实现?我认为这是因为这样做很简单,但我不知道真正的答案是否公开。所以是的,我的回答证实了 OP 的期望。在某种程度上,+ 就像{ get; set; } 这样的语法糖。
  • @phoog 但是,您的答案显然更好,因为它涉及规格并包含更多“技术背景”。但它既没有说明为什么string.Concat 而不是其他东西,也没有说明为什么+ 不仅仅是简单地重载。
  • 为什么+ 没有超载:很难找到不做某事的理由。我从来没有对我的老板说“今天,我没有写排序方法,因为......”。由于不知道原因,我猜测。 (我现在有一个模糊的回忆,我曾在第 9 频道的视频中听到有人讨论过这个问题,但我不确定。)为什么string.Concat?我得出的结论是,它在技术上是一个实现细节,但很难看出 C# 编译器的作者如何做出任何其他选择并且仍然被认为是理智的。
猜你喜欢
  • 1970-01-01
  • 2011-06-09
  • 2013-07-03
  • 2016-11-21
  • 2011-04-26
  • 2013-06-09
  • 2017-09-03
  • 2015-05-08
相关资源
最近更新 更多