記事内に広告が含まれています

C#入門⑤|コレクション(配列・List・Dictionary)の基本

C#入門⑤ 基本文法・構文解説

前回は、演算子の基本について学びました。

今回は、実務でよく使われるコレクションである「配列」「リスト」「ディクショナリ」について、基本的な使い方を初心者向けにわかりやすく解説します。

コレクションとは?

複数の値を一括で管理したいときに使うのがコレクションです。

C#には様々なコレクションが用意されていますが、まずは「配列」「リスト」「ディクショナリ」の3つを押さえておけば十分です。

配列

配列は、同じ型の複数の値をまとめて管理できる構造です。

C#では最もシンプルなコレクションとして扱われます。

宣言と初期化

配列の宣言には複数の書き方があります。どの方法でも、結果として同じ配列が作成されます。

var fruits1 = new string[] { "Apple", "Banana", "Cherry" }; // varを使う場合はnewが必要
string[] fruits2 = { "Apple", "Banana", "Cherry" };         // varを使わない場合はnewを省略できる
string[] fruits3 = ["Apple", "Banana", "Cherry"];           // C# 12以降のコレクション式

どの書き方でも問題ありませんが、C# 12以降であればコレクション式を使うのがいいでしょう。

要素の取り出し

配列の各要素には0から始める番号(=インデックス)が振られています。

以下のようにインデックスを指定することで、配列内の特定の要素を取り出すことができます。

var fruits = new string[] { "Apple", "Banana", "Cherry" };

Console.WriteLine(fruits[0]); // 出力:Apple
Console.WriteLine(fruits[2]); // 出力:Cherry

存在しないインデックスを指定すると、実行時にIndexOutOfRangeExceptionというエラーが発生するので注意してください。

var fruits = new string[] { "Apple", "Banana", "Cherry" };

Console.WriteLine(fruits[3]); // エラー:インデックスが範囲外

配列を扱う際は、インデックスが配列の長さ内に収まっていることを常に意識しましょう。

全要素をループで処理

配列の全要素を繰り返し処理するには、foreachを使うのが便利です。

以下は配列内の全要素をコンソールに出力する例です。

var fruits = new string[] { "Apple", "Banana", "Cherry" };

// 配列 fruits の全要素を順番に取り出して処理する
foreach (var fruit in fruits)
{
    // 現在の要素(fruit)をコンソールに表示する
    Console.WriteLine(fruit);
}

実務で配列を使う主なケース

実務では次に紹介するリストよりも使う場面は限られますが、以下のケースで使われます。

  • パフォーマンス重視の処理(例:画像処理、音声処理、ゲームロジックなど)
  • 要素数が明確で変化しない場面
  • メモリ消費を最小限にしたいとき

List<T>(リスト)

List<T>は、配列と同じく、同じ型の複数の値をまとめて管理できるコレクションですが、要素数を自由に変えられるのが特徴です。

実務で非常によく使われるので、基本的な使い方は確実に押さえておきましょう。

宣言と初期化

リストは、以下のようにして宣言・初期化します。

var fruits1 = new List<string> { "Apple", "Banana", "Cherry" };
List<string> fruits2 = new() { "Apple", "Banana", "Cherry" };   // C# 9以降はnewの後ろの型名を省略可
List<string> fruits3 = ["Apple", "Banana", "Cherry"];           // C# 12以降のコレクション式

// 初期値を指定しない場合は空のリストが生成される
var fruits4 = new List<string>();

List<T>Tの部分にリストに入れたい要素の型を指定します。今回のように List<string>であれば 、文字列だけを扱うリストになります。

このように様々な型に対応できるように作られた仕組みを「ジェネリック」といいます。

ちなみに T は「Type(型)」の頭文字で、「ここに型が入りますよ」という意味を持っています。

基本的な使い方

以下は要素の追加や削除を行い、中身を表示する例です。

インデックスを使った要素の取得や、foreachループによる全要素の処理は配列と同じです。

// リストの初期化(要素数0の空のリストを作成)
var numbers = new List<int>();

// 要素の追加
numbers.Add(10);
numbers.Add(20);
numbers.Add(30);

// インデックス1の要素を取得
Console.WriteLine(numbers[1]); // 出力: 20

// リストの要素数を取得
Console.WriteLine(numbers.Count); // 出力: 3

// 要素の削除
numbers.Remove(20); // 値20を持つ要素を削除(該当要素があれば)

// 全要素を順に取り出して表示
foreach (int num in numbers)
{
    Console.WriteLine(num);
}
// 出力結果:
// 10
// 30

Listと配列の使い分け

Listと配列の大きな違いは「要素を後から追加・削除できるかどうか」です。

  • List は自由に要素を追加・削除できる
  • 配列 はサイズが固定されていて、後から増減できない

実務では、基本的にListを使えば困ることはほとんどありませんが、以下のような場合には配列を使った方がよいこともあります。

  • 「最初から要素数が固定で今後も変わらない」
  • 「できるだけ処理速度やメモリ効率を高めたい」

用途に応じて使い分けるようにしましょう。

Dictionary<TKey, TValue>(ディクショナリ)

Dictionaryは、キーと値をセットで管理するコレクションです。

連想配列やマップとも呼ばれ、「名前(キー)」と「年齢(値)」のように、関連するデータをペアで扱いたいときに便利です。

宣言と初期化

ディクショナリは、以下のように宣言・初期化します。

var ages1 = new Dictionary<string, int>
{
    { "Alice", 30 },
    { "Bob", 25 },
    { "Charlie", 35 }
};

// C# 9以降はnewの後ろの型名を省略可
Dictionary<string, int> ages2 = new()
{
    { "Alice", 30 },
    { "Bob", 25 },
    { "Charlie", 35 }
};

// 初期値を指定しない場合は空のディクショナリが生成される
var ages3 = new Dictionary<string, int>();

リストと同様にジェネリックの仕組みが使われており、宣言時に<キーの型, 値の型>を指定します。

基本的な使い方

以下は要素(キー・値)の追加や削除を行い、中身を表示する例です。

// Dictionaryの宣言と初期化
var ages = new Dictionary<string, int>();

// キーと値を追加
ages.Add("Alice", 30);
ages.Add("Bob", 25);
ages.Add("Charlie", 35);

// キーから対応する値を取り出す
Console.WriteLine(ages["Alice"]);  // 出力: 30

// キーから対応する要素を削除
ages.Remove("Bob");

// 全要素を順に取り出して表示
foreach (var pair in ages)
{
    Console.WriteLine($"{pair.Key} は {pair.Value} 歳です");
}
// 出力結果:
// Alice は 30 歳です
// Charlie は 35 歳です

値の安全な取得(TryGetValue)

上の例では、ages["Alice"]のようにキーを直接指定して値を取得しましたが、もしキーが存在しない場合はKeyNotFoundExceptionというエラーが発生します。

キーが存在しない場合でもエラーを発生させたくない場合は、TryGetValueを使うと安全です。

// 対象のキーがディクショナリに存在するかチェック
if (ages.TryGetValue("Charlie", out int age))
{
    // 対象のキーが存在した場合(ageには対象要素の値が入る)
    Console.WriteLine($"Charlieは{age}歳です");
}
else
{
    // 対象のキーが存在しない場合
    Console.WriteLine("Charlieは登録されていません");
}

値の安全な追加(TryAdd)

上の例では、Addメソッドを使って要素を追加しましたが、もしキーが既に存在する場合はArgumentExceptionというエラーが発生します。

エラーを発生させたくない場合は、TryAddを使うと安全です。(.NET 5以降で使用可能)

if (ages.TryAdd("Alice", 30))
{
    // 対象のキーが存在しなかった場合(追加成功)
    Console.WriteLine("要素が追加されました");
}
else
{
    // 対象のキーが存在した場合(追加されない)
    Console.WriteLine("要素は追加されませんでした");
}

なお以下のように直接キーを指定した場合は、キーが存在しなければ新規追加、存在すれば値が上書きされるので注意してください。

ages["Alice"] = 30;  // 新規追加
ages["Alice"] = 35;  // 上書き(値が30 → 35になる)

Console.WriteLine(ages["Alice"]);  // 出力: 35

まとめ

C#では、目的に応じてコレクションを使い分けることが非常に重要です。

まずは配列、List、Dictionaryの3つをしっかり理解しておけば、実務の多くの場面に対応できます。

コレクション特徴適した場面
配列固定長・高速サイズが固定で高速処理したいとき
List<T>可変長・順序付き要素の数が変動する場合
Dictionary<TKey, TValue>キーで高速アクセスキーと値形式でデータを管理したいとき

次回は「LINQの基本」について解説します。

LINQはコレクションを効率よく操作するための強力な機能ですので、今回の内容を土台として活用してください。

コメント

タイトルとURLをコピーしました