“参照型”と“値型”をテレビのたとえで一気に理解する C# メモリモデル講座
目次
リモコン派? 本体派?
対象: C# を学び始めたばかりの人
この記事でわかること
- 参照型 (reference type) と 値型 (value type) の違い
- コピー・格納・破棄がどう変わるか
- どちらを選べば失敗しにくいか
1. まず用語を整理しよう
分類 | 主な宣言キーワード・例 | 特徴 |
---|---|---|
参照型(reference type) | class, interface, delegate, 配列 int[], string など | 変数は ヒープ上のオブジェクトへのアドレス を保持。実体は 1 か所、ガベージコレクション (GC) の対象 |
値型(value type) | struct, enum, 組み込み数値型 int, double, bool, char など | 変数が データ本体 をそのまま保持。代入すると丸ごと複製される |
✔︎ ポイント
- class は「参照型を宣言するためのキーワードの一つ」であって “参照型=class” ではありません
- struct や enum を使うと「値型」を宣言できる
2. 参照型は “テレビ + リモコン”
構成要素 | たとえ | 振る舞い |
---|---|---|
変数 | テレビの リモコン | リモコン本体は小さく、ボタンを押すと本体が動く |
オブジェクト | テレビ本体 | 実体は家に 1 台だけ。リモコンが何個あっても共有 |
コピー | リモコンをもう 1 台配る | どのリモコンから操作しても同じテレビが反応 |
エラー | テレビの電源コードを抜くと全リモコンが無力 | C# では null 参照例外 (NullReferenceException) |
コードで体験
class Television
{
public int Volume { get; set; }
}
var tvA = new Television { Volume = 5 };
var tvB = tvA; // リモコンをもう 1 個
tvB.Volume = 10; // どのリモコンでも同じテレビ
Console.WriteLine(tvA.Volume); // 10
3. 値型は “テレビ本体を机にドン!”
構成要素 | たとえ | 振る舞い |
---|---|---|
変数 | 前面操作パネル付きテレビ本体 | 変数そのものがテレビを抱える |
コピー | テレビをまるごと複製して隣に置く | 操作は完全に独立、干渉しない |
破棄 | テレビを机からどければ終わり | スコープを抜ければ自動回収 (GC 不要) |
コードで体験
struct FrontPanelTv
{
public int Volume { get; set; }
}
var fpA = new FrontPanelTv { Volume = 5 };
var fpB = fpA; // 本体を箱ごとコピー
fpB.Volume = 10; // 独立した 2 台目
Console.WriteLine(fpA.Volume); // 5
4. 参照型 vs 値型 ── 一覧で比較
特性 | 参照型 (class など) | 値型 (struct など) |
---|---|---|
格納先 | 変数はアドレス、実体はヒープ | 変数内に実体を直格納 |
コピー | アドレス複製 → 同じオブジェクト共有 | データ丸ごと複製 → 独立オブジェクト |
GC の影響 | ヒープ解放は GC 任せ | スタック領域はスコープで自動消滅 |
== 既定 | 参照比較 | 値比較 (フィールドごと) |
null 許容 | あり | 基本なし (T? で nullable にできる) |
適材適所 | 複雑・可変なデータ/共有したいとき | 小さくて不変なデータ/多数扱うとき |
5. 選び方のチェックリスト
質問 | YES | NO |
---|---|---|
データは 16 byte 以下 & 変更不可? | 値型で OK | 参照型を検討 |
同じデータを複数場所で共有したい? | 参照型にすべき | 値型でも可 |
GC 圧迫を絶対に避けたい? | 値型を優先 | 参照型でも問題なし |
ボックス化 (object への暗黙変換) が起きる? | 参照型に切り替え | 値型のままでも可 |
6. まとめ
- 参照型 = リモコン方式
- 変数は小さいアドレスだけ
- コピーは軽いが null と競合に注意
- 値型 = 本体直置き方式
- コピーが重い可能性はあるが独立性が高い
- 小さく不変なら最高に高速
覚え方
- リモコンが要るのが参照型
- 机に直置きが値型
これさえ頭に入れておけば、C# のメモリモデルで迷子になることはありません。
訪問数 3 回, 今日の訪問数 1回
ディスカッション
コメント一覧
まだ、コメントがありません