【混乱ポイント解消】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 += "太郎";

これは「山田」を変更しているのではありません。

実際は:

  1. 「山田太郎」という新しい文字列を作る
  2. 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 は新しい文字列を作るから。


訪問数 5 回, 今日の訪問数 5回

C#

Posted by hidepon