List<T> とは何か? なぜ配列より便利か?
C#で複数のデータをまとめて扱う最も基本的な方法は「配列(T[])」です。しかし、配列には「一度作成するとサイズ(要素数)を変更できない」という大きな制約があります。
// 3個の要素しか入らない配列
int[] scores = new int[3];
scores[0] = 100;
scores[1] = 90;
scores[2] = 80;
// scores[3] = 70; // 実行時エラー (IndexOutOfRangeException)
後からデータを追加したり、途中のデータを削除したりしたい場合、配列のままでは非常に不便です。
この問題を解決するのが、System.Collections.Generic名前空間にある List<T>(ジェネリックリスト)です。
List<T>は、内部的に配列を使用しながらも、必要に応じて自動的にサイズを拡張・縮小してくれる「動的サイズの配列」のように振る舞います。C#において最も頻繁に使用されるコレクション(データの集まり)の一つです。
この記事では、List<T>の基本的な操作(初期化、追加、削除、アクセス)について解説します。
List<T> を使用するための準備
List<T>を使用するには、コードの先頭でSystem.Collections.Generic名前空間をusingする必要があります。
using System;
using System.Collections.Generic; // List<T> を使うために必要
List<T> の基本的な操作
List<T>の操作は、メソッド呼び出しによって直感的に行えます。
1. 初期化と Add (要素の追加)
new List<T>() でインスタンスを作成します。Tの部分には、格納したいデータ型(string, int, doubleなど)を指定します。
要素を追加するには、Addメソッドを使用します。Addは、リストの末尾に要素を追加します。
// string 型を格納する List を作成
var userNames = new List<string>();
// Add メソッドで末尾に要素を追加
userNames.Add("Alice");
userNames.Add("Bob");
userNames.Add("Charlie");
2. Count プロパティ (要素数の取得)
リストに現在いくつの要素が含まれているかを取得するには、Countプロパティを使用します。 (配列のLengthプロパティに相当しますが、名前が異なる点に注意してください)
// 3 が出力される
Console.WriteLine($"現在の要素数: {userNames.Count}");
3. インデックスによるアクセスと変更
List<T>は配列と同様に、0から始まるインデックス([])を使用して、特定の要素にアクセスしたり、値を変更したりできます。
// インデックス 1 (2番目) の要素を取得
string secondUser = userNames[1]; // "Bob"
Console.WriteLine($"2番目のユーザー: {secondUser}");
// インデックス 1 の値を "Brian" に上書き
userNames[1] = "Brian";
Console.WriteLine($"変更後の2番目: {userNames[1]}");
4. Insert と Remove (要素の挿入と削除)
List<T>の真価は、要素の挿入と削除が容易な点にあります。
Insert(int index, T item): 指定したindexの位置にitemを挿入します。後ろにあった要素は自動的に1つずつ後ろにずれます。Remove(T item): リスト内で最初に見つかったitemを削除します。後ろの要素は自動的に前に詰められます。
// 先頭 (インデックス 0) に "SystemAdmin" を挿入
userNames.Insert(0, "SystemAdmin");
// "Charlie" という値を持つ要素を検索して削除
userNames.Remove("Charlie");
foreach による反復処理
List<T>に含まれるすべての要素を順番に処理するには、配列と同様にforeachループを使用するのが最も簡単です。
コード例:List<T> の一連の操作
ここまでの操作を一つのプログラムにまとめると、以下のようになります。
using System;
using System.Collections.Generic; // List<T> を使うために必要
public class ListBasicExample
{
public static void Main()
{
// 1. List<string> の初期化
var userNames = new List<string>();
Console.WriteLine($"初期状態 (要素数: {userNames.Count})");
// 2. Add: 末尾に要素を追加
userNames.Add("Alice");
userNames.Add("Bob");
userNames.Add("Charlie");
Console.WriteLine($"\n--- Add 後の状態 (要素数: {userNames.Count}) ---");
PrintList(userNames); // [Alice] [Bob] [Charlie]
// 3. Insert: インデックス 1 に挿入
userNames.Insert(1, "Brian");
Console.WriteLine($"\n--- Insert(1, \"Brian\") 後の状態 ---");
PrintList(userNames); // [Alice] [Brian] [Bob] [Charlie]
// 4. Remove: "Bob" を削除
userNames.Remove("Bob");
Console.WriteLine($"\n--- Remove(\"Bob\") 後の状態 ---");
PrintList(userNames); // [Alice] [Brian] [Charlie]
// 5. インデックスによる変更
if (userNames.Count > 0)
{
userNames[0] = "SystemAdmin"; // "Alice" を "SystemAdmin" に変更
}
Console.WriteLine($"\n--- インデックス[0] を変更後 ---");
PrintList(userNames); // [SystemAdmin] [Brian] [Charlie]
}
// List<string> の内容をコンソールに出力するヘルパーメソッド
private static void PrintList(List<string> list)
{
// 6. foreach による反復処理
foreach (var item in list)
{
Console.Write($"[{item}] ");
}
Console.WriteLine();
}
}
出力結果:
初期状態 (要素数: 0)
--- Add 後の状態 (要素数: 3) ---
[Alice] [Bob] [Charlie]
--- Insert(1, "Brian") 後の状態 ---
[Alice] [Brian] [Bob] [Charlie]
--- Remove("Bob") 後の状態 ---
[Alice] [Brian] [Charlie]
--- インデックス[0] を変更後 ---
[SystemAdmin] [Brian] [Charlie]
まとめ
List<T>は、C#でデータを扱う上で配列(T[])と並んで(あるいはそれ以上に)重要なコレクションです。
- 配列 (
T[]): サイズが固定。 List<T>: サイズが動的。Add,Insert,Removeで要素数を自由に変更できる。
プログラム実行時に要素数が可変(増減する可能性がある)場合は、List<T>の使用が最適です。
