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