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

时间:2013-01-23 06:23:14

标签: c# .net string compiler-construction 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);
}

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

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

        Console.WriteLine(str);
    }

它运作得很好,

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

4 个答案:

答案 0 :(得分:7)

首先,运算符+=不能重载。如果你有表达式A += B,那么它就像你写的那样编译:*

A = A + B

好的,这就是为什么string不会重载operator +=(因为它不能重载)。那么,为什么它也不会超载operator +?这只是CLR和C#之间的又一个区别。 C#编译器知道像stringint这样的类型是特殊的,它为其运算符生成特殊代码(为string.Concat()调用stringadd int)的说明。

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

  1. 您不希望每个int添加都被编译为方法调用,这会增加很多开销。因此,使用了int添加的特殊说明。
  2. 对于溢出,整数加法的行为并不总是相同。有一个编译器开关可以为溢出抛出异常,您还可以使用checkedunchecked运算符。如果只有operator +,编译器应如何处理? (它实际上做的是使用指令add进行未经检查的溢出,并使用add.ovf进行已检查的溢出。)
  3. 出于性能原因,您还希望以特殊方式处理string添加。例如,如果您有string s abc并写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;

答案 1 :(得分:5)

+=运算符没有重载,var = var + newValue短手。字符串的情况也是如此。

+= Operator (C# Reference)

  

+ =运算符不能直接重载,而是用户定义的类型   可以重载+运算符

考虑以下示例:

string str = "new string";
str += "new value";

这等于:

str = str + "new value";

在编译时内部调用string.Concat

答案 2 :(得分:3)

+=没有明确实现,但它起作用,因为编译器做了它的魔术

str += "World";

str =  str + "World";

str = str.Concat("World");

答案 3 :(得分:0)

如上所述,根据.NET,string += otherString相当于

string = string + otherString

This .NET link提到了连接运算符,this .NET link讨论了这两个操作之间的关系。