本文へスキップ
BecomeCoder

C#オブジェクト指向コース · 第2章 型を表現する · レッスン20

メモリモデルとGC

ブラウザで完結

導入

「値型と参照型で挙動が違う」のはなぜか——その答えはメモリの使われ方にあります。値はスタック、オブジェクトの実体はヒープに置かれ、不要になった実体は**GC(ガベージコレクタ)**が自動で回収します。C/C++と違い手動解放は不要ですが、ファイルや接続などの外部資源だけはIDisposableで明示的に片付けます。この全体像を掴むと、参照の共有やメモリ効率の判断ができるようになります。

図解

flowchart TB
    subgraph Stack["スタック(高速・自動)"]
        V["値型 int / 変数そのもの"]
    end
    subgraph Heap["ヒープ(GCが管理)"]
        O["参照型の実体<br/>class・配列・List"]
    end
    V -.->|参照型の変数は実体を指す| O
    GC["GC が不要な実体を自動回収"] --> Heap

サンプル

// 参照型の代入は「同じ実体」を指す(値のコピーではない)
var arr = new[] { 1, 2, 3 };
var b = arr;           // 参照のコピー(同じ配列を指す)
b[0] = 99;
Console.WriteLine(arr[0]);   // 99 ← 同じ実体を共有しているため

// 使い終わった実体は GC が自動回収する。手動 free は不要。
// ただし「ファイル・DB接続」など外部資源は IDisposable で明示的に解放する
using (var res = new Resource())
{
    res.Use();
}   // ブロックを抜けると自動的に Dispose() が呼ばれる
Console.WriteLine("解放済み");

class Resource : IDisposable
{
    public void Use() => Console.WriteLine("使用中");
    public void Dispose() => Console.WriteLine("後片付け");
}
  • 値型(int/struct)は値そのもの、参照型(class/配列/List)は「実体を指す矢印」
  • 参照型の代入・引数渡しは同じ実体を共有する(struct/classの違いの根拠)
  • 不要になった実体はGCが自動で回収するのでメモリ解放は基本気にしなくてよい
  • ファイル・接続など外部資源はIDisposableusingで確実に解放する(usingの背景)

演習

var list1 = new List<int> { 1, 2, 3 };
var list2 = list1;      // 参照のコピー(同じ実体)
list2.Add(4);

// TODO: list1 の要素数を出力してください(同じ実体なので 4)
___
  • 期待される出力: 4
ヒント1を見る

list2list1と同じ実体なので、Addは両方に反映されます

ヒント2を見る

Console.WriteLine(list1.Count);

まとめ

  • 値型はスタック、参照型の実体はヒープに置かれる
  • 参照型の代入は実体の共有(値のコピーではない)
  • 不要な実体はGCが自動回収、外部資源はIDisposableusingで解放

次章: 良い設計の指針「SOLID原則」へ進みます。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。