【混乱ポイント解消】stringは参照型なのに、なぜコピーしても影響しないの?
C#を学んでいると、必ず出てくる疑問があります。
stringって参照型ですよね?
なのにコピーしても元が変わらないのはなぜ?
今日はこのモヤモヤをきれいに整理します。
まず「普通の参照型」を確認
class Person
{
public string Name;
}
var p1 = new Person();
p1.Name = "山田";
var p2 = p1;
p2.Name = "佐藤";
Console.WriteLine(p1.Name);
出力:
佐藤
なぜ?
- p1 と p2 は同じオブジェクトを指している
- 参照がコピーされただけ
- 実体は1つ
これが典型的な「参照型」です。
次に string を見てみましょう
string s1 = "山田";
string s2 = s1;
s2 = "佐藤";
Console.WriteLine(s1);
出力:
山田
「あれ?変わらない?」
ここが今日の核心です。
stringは参照型です
確認してみます。
Console.WriteLine(typeof(string).IsValueType);
結果:
False
つまり string は参照型です。
ではなぜ挙動が違うのでしょうか?
理由は「不変(immutable)」だから
stringは一度作ったら中身を変更できません。
例えば:
string s = "山田";
s += "太郎";
これは「山田」を変更しているのではありません。
実際は:
- 「山田太郎」という新しい文字列を作る
- s にそれを代入している
だけです。
イメージ図で理解する
最初:
s1 → "山田"
s2 → "山田"
s2 = “佐藤” の後:
s1 → "山田"
s2 → "佐藤"
「山田」はそのまま残っています。
なぜなら string は変更できないからです。
つまりこういうこと
| 型 | コピー後どうなる? |
|---|---|
| int | 値がコピーされる |
| class | 参照がコピーされる |
| string | 参照型だが変更不可なので結果的に値型のように見える |
重要ポイント
string は
✔ 参照型
✔ でも変更できない
✔ だから安全
なぜこういう設計なのか?
もし string が変更可能だったら、
string a = "テスト";
string b = a;
b[0] = 'ベ'; // こんなことができたら…
a まで変わってしまいます。
これは危険です。
文字列はプログラム中で大量に使われるため、
「安全性」を優先して設計されています。
さらに一歩(上級)
string には intern(文字列プール)という仕組みもあります。
同じ文字列リテラルはメモリを共有します。
しかし、不変なので問題は起きません。
同じ文字列リテラル(例:“Hello”)が複数回使われた場合、メモリ上には1つだけ作られ、それを共有します。これによりメモリを節約できます。通常の参照型なら共有は危険ですが、stringは不変(immutable)で中身を変更できないため、安全に共有できます。この設計により、安全性と効率性の両立が実現されています。
今日のまとめ
stringは:
「参照型の顔をした、値型のように振る舞う安全設計オブジェクト」
理解チェック
なぜ以下は安全ですか?
string a = "Hello";
string b = a;
b += " World";
答えは:
→ b は新しい文字列を作るから。





ディスカッション
コメント一覧
まだ、コメントがありません