System.String不会重载operator + =但是String Concatenation有效,怎么样?

PaR*_*RaJ 5 .net c# compiler-construction string clr

System.String只有两个运算符重载

public static bool operator ==(string a, string b)
{
  return string.Equals(a, b);
}

public static bool operator !=(string a, string b)
{
  return !string.Equals(a, b);
}
Run Code Online (Sandbox Code Playgroud)

但是当使用+ = for String concat时,示例:

    private static void Main()
    {
        String str = "Hello ";
        str += "World";

        Console.WriteLine(str);
    }
Run Code Online (Sandbox Code Playgroud)

它工作得很好,

那么,为什么System.String不会重载运算符+ = it Concats字符串?

svi*_*ick 8

首先,操作员+=不能超载.如果你有表达式A += B,那就像你写的一样编译:*

A = A + B
Run Code Online (Sandbox Code Playgroud)

好的,这就是为什么string不重载operator +=(因为它不能超载).那么,为什么它也不会超负荷operator +?这只是CLR和C#之间的又一个区别.C#编译器知道类型的喜欢stringint比较特殊,它生成的运营商特殊的代码(调用string.Concat()string,或add指令int).

为什么这些运营商以特殊方式对待?因为你希望他们以特殊的方式对待他们.我认为这是最清楚的int:

  1. 您不希望将每个int添加项编译为方法调用,这会增加很多开销.因此,使用了特殊的添加指令int.
  2. 对于溢出,整数加法的行为并不总是相同.有一个编译器开关可以为溢出抛出异常,您也可以使用checkedunchecked运算符.如果只有它,编译器应如何处理operator +?(它实际上做的是使用指令add进行未经检查的溢出和add.ovf检查溢出.)

string出于性能原因,您也希望以特殊方式处理添加.例如,如果你有strings a,b然后c编写a + b + c,然后你编译它作为两个调用operator +,你需要string为结果分配一个临时的a + b,这是低效的.相反,编译器生成该代码string.Concat(a, b, c),它可以直接只分配一个所需长度的字符串.


*这不完全正确,有关详细信息,请参阅Eric Lippert的文章Compound Assignment,Part One和C#规范的§7.17.2.还要注意缺少的分号,A += B实际上是一个表达式,例如,你可以写X += Y += Z;.


Hab*_*bib 5

有没有过载的+=运营商,它的一个速记var = var + newValue.字符串的情况也是如此.

+ =运算符(C#参考)

+ =运算符不能直接重载,但用户定义的类型可能会使+运算符重载

请考虑以下示例:

string str = "new string";
str += "new value";
Run Code Online (Sandbox Code Playgroud)

这相当于:

str = str + "new value";
Run Code Online (Sandbox Code Playgroud)

string.Concat在编译时内部调用.