List と配列 (T[]) の違いを押さえる ── 初学者向けガイド

はじめに

C# を学び始めると int[] nums = { 1, 2, 3 }; のような 配列 と

var list = new List<int> { 1, 2, 3 }; のような List<T> が並行して登場します。

どちらも「複数の要素をまとめる」ための型ですが、設計思想・メモリ管理・使い勝手が大きく異なります。本記事では 6つの観点 で両者を比較し、最後に「いつどちらを選ぶべきか」という指針をまとめます。


配列 (T[]) とは

  • 固定長 の連続メモリ領域を確保する、最もプリミティブなコレクション
  • CLR が直接サポートするため 要素アクセスが最速
  • 型は 参照型(object から派生)だが、int[] などの 値型要素 を持つことも可能
  • 一度確保したサイズは不変。追加・削除には Array.Resize などで 新しい配列を再生成 する必要がある
int[] scores = new int[3]; // 要素数3で確保
scores[0] = 85;

List<T> とは

  • System.Collections.Generic 名前空間で提供される ジェネリック クラス
  • 内部では 配列をラップ し、サイズ超過時に自動的に再確保 (容量を約2倍)
  • Add, Remove, Insert, Sort, Find など 豊富なメソッド を具備
  • キャパシティ自動拡張のおかげで 可変長 コレクションとして直感的に扱える
var scores = new List<int> { 85 };
scores.Add(92);            // サイズを意識せず要素を追加

6つの観点で比較

観点配列 (T[])List<T>
サイズ変更不可 (再生成が必要)可能 (内部で容量を再確保)
メモリ配置要素が連続配置。Overhead 最小内部配列 + List オブジェクト分の Overhead
要素アクセス速度最速 (境界チェックのみ)わずかに遅い (List オブジェクト経由)
メソッド数Length など最小限追加・削除・検索・並べ替えなど豊富
LINQ/foreachどちらも対応どちらも対応 (差はない)
用途の典型例固定長データ、低レベル最適化可変長データ、ビジネスロジック全般

Tip: List<T>.Capacity は現在確保している内部配列の長さを示します。大量追加が確定している場合は、先に Capacity を設定して再確保を 1 回に抑えるとパフォーマンスが向上します。


パフォーマンスのイメージ

// List<T> は自動で容量を2倍前後に拡張する
var list = new List<int>(2);   // Capacity = 2
list.AddRange(new[]{1,2});
list.Add(3);                   // Capacity 4 に拡張(再確保コスト発生)

// Array.Resize は毎回コピーが走る
int[] arr = {1,2};
Array.Resize(ref arr, 3);      // 新配列を作成してコピー
arr[2] = 3;
  • 少量の追加なら List のコストは誤差ですが、数万件以上 を段階的に追加する場合は Capacity を最初に見積もるか、ArrayPool<T> を検討すると良いでしょう。

どちらを選ぶ?── 実務での指針

要件推奨
要素数が コンパイル時に決定/変更しない配列
動的に追加・削除 したいList<T>
最高速を追求する低レベル APISpan<T> / Memory<T> / 配列
Unity など GC を避けたい 場面配列 or NativeArray など
LINQ・検索・並べ替えを多用List<T>

よくある落とし穴

  1. 再確保コストの無視
var l = new List<int>();
for (int i = 0; i < 1_000_000; i++) l.Add(i); // 階段的に容量倍増 → 何度もコピー
  1. ➡ new List<int>(1_000_000) で初期容量を指定しましょう。
  2. ToArray() vs AsSpan() の使い分け
    • ToArray() は 完全コピー です。読み取り専用で良いなら AsReadOnly() や Span<T> を検討。
  3. 多次元データの誤用
    • int[,] (多次元配列) は行列計算で便利ですが foreach が遅くなりがち。
    • 大規模データなら ジャグ配列 (int[][]) や List<List> の方がキャッシュ効率が良いケースもあります。

まとめ

キー概念配列List<T>
特徴固定長・最速アクセス可変長・メソッド豊富
適材適所高速処理・GC 圧縮ビジネスロジック・柔軟性
  • 固定長・パフォーマンス優先 → 配列
  • 柔軟性・開発効率優先 → List<T>

現場では2つを併用することがほとんどです。アルゴリズム部分は配列で書き、外からは IReadOnlyList<T>インターフェースで隠蔽しておけば、将来 List でも配列でも差し替え可能になります。

「道具箱にドライバーと電動ドライバーが両方入っている」イメージで、用途に合わせて選択する習慣を身につけましょう。

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

C#,List,配列

Posted by hidepon