文字列が不変であるだけでなく、string
は参照型ですが、参照自体はそうではありません。つまり、string
参照渡しですが、参照自体は値渡しです。
したがって、参照型の場合、(変更可能である限り) パラメーターによって参照されるオブジェクトを変更できますが、参照渡ししない限り、引数が参照するものを変更することはできません。
したがって、string
変数が参照するものを変更しようとすると、次のようになります。
str = tmpStr;
ローカルで参照するものを変更しますstr
が、元の引数が参照するものには影響しませんlocalString
。
localString
このように考えてください。引数が位置 1000 のオブジェクトを参照しているとしましょう。
localString
+---------------+ 1000
| 1000 | -----------------> +---------------+
+---------------+ | Count: 1 |
| Value: "" |
+---------------+
次に、メソッドに渡すlocalString
と、参照のコピーが作成され (as としてstr
)、参照カウントが更新されます...
localString
+---------------+ 1000
| 1000 | -----------------> +---------------+
+---------------+ | Count: 2 |
| Value: "" |
str +---------------+
+---------------+ ^
| 1000 | ---------------------+
+---------------+
次に、str を新しい文字列に割り当てると、参照は変更されますstr
が、変更されませんlocalString
。
localString
+---------------+ 1000
| 1000 | -----------------> +---------------+
+---------------+ | Count: 1 |
| Value: "" |
str +---------------+
+---------------+ 2500
| 2500 | ---------------------> +---------------+
+---------------+ | Count: 1 |
| Value: ... |
+---------------+
したがって、元の参照ではなく、参照するstr
もののみを変更した場合、それを変更したい場合は、参照渡しします。つまり、元の引数への参照になります (ptr から ptr に似ています)。str
localString
str
localString
+---------------+ 1000
| 2500 | ------------------> +---------------+
+---------------+ | Count: 2 |
^ | Value: "" |
str | +---------------+
+---------------+
| |
+---------------+
ここで、str
変更すると参照も変更localString
されます。
localString
+---------------+ 1000
| 1000 | -----+ +---------------+
+---------------+ | | Count: 0 |
^ | | Value: "" |
str | | +---------------+
+---------------+ | 2500
| | +----------------> +---------------+
+---------------+ | Count: 1 |
| Value: ... |
+---------------+
そしてもちろん、元の文字列 (この例のように他に何も参照されていないと仮定) は、ガベージ コレクトすることができます...
そのため、本当にstring
パラメーターを変更したい場合は、ref
またはで渡すか、変更されout
た新しいバージョンを返すか、インスタンス メンバーに格納します (ただし、pass-by-instance-member はカップリングの高次であり、他のエラーを引き起こす可能性があります)。問題...)。