まず、演算子+=
はオーバーロードできません。式がある場合A += B
、次のようにコンパイルされます:*
A = A + B
オーケー、それがstring
オーバーロードしない理由ですoperator +=
(オーバーロードできないからです)。では、なぜ過負荷にならないoperator +
のでしょうか? これは、CLR と C# のもう 1 つの違いにすぎません。C# コンパイラは、 や のような型string
がint
特殊であることを認識しており、それらの演算子用に特別なコードを生成します ( string.Concat()
for string
、またはadd
for の命令を呼び出しint
ます)。
これらの演算子が特別な方法で扱われるのはなぜですか? 特別扱いしてほしいからです。これは次の場合に最も明確だと思いますint
:
- 各
int
追加をメソッド呼び出しとしてコンパイルしないと、多くのオーバーヘッドが追加されます。そのため、加算用の特別な命令int
が使用されます。
- 整数加算は、オーバーフローに関して常に同じように動作するとは限りません。
checked
オーバーフローの例外をスローするコンパイラ スイッチがあり、 andunchecked
演算子も使用できます。しかなかった場合、コンパイラはそれをどのように処理する必要がありoperator +
ますか? (実際に行うことはadd
、未チェックのオーバーフローとチェック済みのオーバーフローに命令を使用することadd.ovf
です。)
string
また、パフォーマンス上の理由から、足し算も特別な方法で扱いたいと考えています。たとえば、string
s a
、b
andc
と write がa + b + c
あり、それを の 2 つの呼び出しとしてコンパイルした場合、 の結果にoperator +
一時を割り当てる必要がありますが、これは非効率的です。代わりに、コンパイラはそのコードを として生成し、必要な長さの文字列を 1 つだけ直接割り当てることができます。string
a + b
string.Concat(a, b, c)
* これは厳密には正しくありません。詳細については、Eric Lippert の記事「Compound Assignment, Part One and Compound assignment in the C# specification」を参照してください。また、欠落しているセミコロンにも注意してください。A += B
実際には式です。たとえば、次のように記述できますX += Y += Z;
。