System.String 不会重载运算符 += 但字符串连接可以工作,如何实现?

问题描述 投票:0回答:4

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);
}

但是当使用 += 进行字符串连接时,示例:

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

        Console.WriteLine(str);
    }

效果很好,

那么,如果 System.String 没有重载运算符 += 它如何连接字符串呢?

c# .net string clr
4个回答
8
投票

首先,运算符

+=
不能重载。如果你有表达式
A += B
,它的编译就像你写的:*

A = A + B

好吧,这就是为什么

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

为什么这些操作员会受到特殊对待?因为您希望他们受到特殊的对待。我认为这对于

int
来说是最清楚的:

  1. 您不希望每个
    int
    添加都被编译为方法调用,这会增加大量开销。因此,使用了
    int
    加法的特殊指令。
  2. 整数加法在溢出方面的表现并不总是相同。有一个编译器开关可以抛出溢出异常,您还可以使用
    checked
    unchecked
    运算符。如果编译器只有
    operator +
    应该如何处理? (它实际上的作用是使用指令
    add
    来表示未检查的溢出,使用
    add.ovf
    来检查溢出。)

并且出于性能原因,您也希望以特殊方式处理

string
加法。例如,如果您有
string
s
a
b
c
并编写
a + b + c
,然后将其编译为对
operator +
的两次调用,则需要为
string
的结果,效率很低。相反,编译器会将该代码生成为
a + b
,它只能直接分配所需长度的一个字符串。

* 这并不完全正确,有关详细信息,请参阅 C# 规范中 Eric Lippert 的文章

复合赋值,第一部分复合赋值。另请注意缺少的分号,string.Concat(a, b, c)确实是一个表达式,例如,您可以写

A += B
    


5
投票
X += Y += Z;

运算符没有重载,它是

+=
简写。字符串的情况也是如此。

+= 运算符(C# 参考)

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

考虑以下示例:

var = var + newValue

这等于:

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

在编译时内部调用 
str = str + "new value";

    


3
投票
string.Concat

没有显式实现,但它可以工作,因为编译器确实有魔力


+=



0
投票
str += "World"; str = str + "World"; str = str.Concat("World");

相当于


string += otherString

这个 .NET 链接

提到了串联运算符,这个 .NET 链接讨论了两个操作之间的关系。

© www.soinside.com 2019 - 2024. All rights reserved.