C#は、進化を続ける強力なプログラミング言語であり、その根幹を支えるデータ構造の一つが配列です。
2026年の現在においても、メモリ効率や実行速度を重視する開発において、配列を正しく使いこなすことは必須のスキルと言えます。
本記事では、C#における配列の宣言方法から、最新の構文を活用した効率的な使い方までを詳しく解説します。
プログラミング初心者の方から、よりパフォーマンスを意識したコードを書きたい中級者の方まで、幅広く役立つ内容を目指しました。
この記事を通じて、配列の基礎と応用をしっかりとマスターしていきましょう。
C#における配列の基本概念
配列とは、同じ型の複数の要素を一つの変数としてまとめて管理するための仕組みです。
C#の配列は固定長であり、一度作成するとそのサイズを変更することはできません。
配列内の各要素には「インデックス(添え字)」を使用してアクセスし、インデックスは常に0から始まります。
メモリ上では連続した領域に配置されるため、要素へのアクセスが非常に高速であるという特徴があります。
大量のデータを一括で処理する場合や、パフォーマンスが要求されるアルゴリズムの実装に最適です。
配列の宣言と初期化のバリエーション
C#で配列を使用するためには、まず配列変数を宣言し、インスタンスを生成する必要があります。
宣言と初期化にはいくつかの書き方があり、状況に応じて最適なものを選択することが重要です。
基本的な宣言と生成
最も標準的な配列の宣言と生成のコードを確認しましょう。
// 要素数5の整数型配列を宣言
int[] numbers = new int[5];
// 要素に値を代入
numbers[0] = 10;
numbers[1] = 20;
このコードでは、int型の要素を5つ持つ配列を確保していますが、初期値はすべて0になります。
コレクション式による初期化(C# 12以降の推奨)
近年のC#において、最も推奨されるモダンな書き方がコレクション式です。
以前の複雑な記述を簡略化し、直感的に配列を定義できるようになりました。
// モダンな配列の宣言と初期化
int[] modernNumbers = [1, 2, 3, 4, 5];
// 文字列の配列も同様に記述可能
string[] fruits = ["Apple", "Banana", "Orange"];
この書き方は可読性が高く、2026年現在の開発現場では標準的に利用されています。
配列の初期化方法まとめ
配列の初期化には以下のようなパターンがあります。
| 記述方法 | 例 | 特徴 |
|---|---|---|
| サイズ指定のみ | new int[3] | 要素は型のデフォルト値(0やnull)で初期化されます。 |
| 初期値指定(従来) | new int[] { 1, 2 } | 明示的に値を指定して生成します。 |
| コレクション式 | [ 1, 2, 3 ] | 最も簡潔で推奨される書き方です。 |
| 暗黙的型付け | var arr = new[] { 1, 2 } | 右辺から型を推論させます。 |
配列要素へのアクセスと操作
配列の要素を操作する際には、インデックスの指定方法を正しく理解しておく必要があります。
インデックスによるアクセス
配列の特定の要素を取得したり、値を書き換えたりするには、[]の中に数値を指定します。
string[] colors = ["Red", "Green", "Blue"];
// 要素の取得
string firstColor = colors[0]; // Red
// 要素の書き換え
colors[1] = "Yellow";
firstColor: Red
colors[1]: Yellow
存在しないインデックス(例えば要素数3の配列でcolors[3])にアクセスしようとすると、IndexOutOfRangeExceptionが発生するため注意が必要です。
末尾からのインデックス(Index型)
C#では、末尾からの位置を指定する^演算子が利用可能です。
^1は「最後から1番目の要素」を指します。
int[] values = [10, 20, 30, 40, 50];
// 最後の要素を取得
int lastItem = values[^1]; // 50
これにより、values[values.Length - 1]と書く手間が省け、コードがスッキリします。
配列の範囲指定(Range型)
配列の一部を切り出して別の配列のように扱いたい場合は、..演算子を使用します。
これを「スライス」と呼びます。
int[] source = [0, 1, 2, 3, 4, 5];
// インデックス1から3の前までを取得(1と2)
int[] slice = source[1..3];
スライス操作によって、部分的なデータ処理が非常に容易になります。
多次元配列とジャグ配列
行列のような複雑なデータを扱うために、C#では多次元配列とジャグ配列が用意されています。
多次元配列(矩形配列)
すべての行の長さが等しい配列を「多次元配列」と呼びます。
// 2行3列の配列
int[,] matrix = new int[2, 3] {
{ 1, 2, 3 },
{ 4, 5, 6 }
};
int val = matrix[1, 2]; // 6
カンマを使用して次元を区切るのが特徴です。
ジャグ配列(配列の配列)
各行の長さが異なる配列を作成できるのが「ジャグ配列」です。
// 配列を要素に持つ配列
int[][] jagged = [
[1, 2],
[3, 4, 5, 6],
[7]
];
int val = jagged[1][2]; // 5
柔軟な構造が必要な場合には、多次元配列よりもジャグ配列が適しています。
配列の繰り返し処理
配列の全要素を走査する方法はいくつかありますが、最も一般的なのはforeach文です。
foreach文による走査
読み取り専用で全要素にアクセスする場合に最適です。
string[] names = ["Alice", "Bob", "Charlie"];
foreach (string name in names)
{
Console.WriteLine(name);
}
foreachはインデックスを管理する必要がないため、書き間違いによるバグを防ぐことができます。
for文による走査
インデックスを直接操作したい場合や、要素の値を変更したい場合にはfor文を使用します。
int[] data = [1, 2, 3];
for (int i = 0; i < data.Length; i++)
{
data[i] *= 2; // 各要素を2倍にする
}
ループの範囲指定には必ず Length プロパティを使用するようにしましょう。
System.Arrayクラスの便利なメソッド
C#の配列はSystem.Arrayクラスを継承しており、便利な静的メソッドが多数用意されています。
- Array.Sort(array):配列の要素を昇順にソートします。
- Array.Reverse(array):配列の要素の順序を反転させます。
- Array.Clear(array):配列の要素を指定範囲で初期化(0やnullに)します。
- Array.IndexOf(array, value):特定の要素が最初に見つかった位置のインデックスを返します。
- Array.Copy(source, destination, length):配列の内容を別の配列へコピーします。
これらのメソッドを活用することで、複雑なアルゴリズムを自分で書く必要がなくなります。
モダンC#におけるパフォーマンス最適化:Span<T>
2026年のC#開発において避けて通れないのが、Span<T>およびReadOnlySpan<T>の活用です。
配列のスライス操作を行う際、従来のsource[1..3]は新しい配列のコピーを作成するため、メモリ消費が発生します。
しかし、Span<T>を使用すれば、メモリのコピーを発生させずに配列の一部を効率よく参照できます。
int[] largeArray = new int[1000];
// メモリコピーを発生させずに範囲を参照
Span<int> span = largeArray.AsSpan(100, 50);
span[0] = 999; // largeArray[100]が書き換わる
高頻度で実行される処理や、大規模なデータ処理を行うシステムでは、このSpan<T>による最適化が非常に効果的です。
配列とList<T>の使い分け
C#には、動的にサイズが変更できるList<T>という便利なクラスも存在します。
「配列とListのどちらを使うべきか」という問いに対しては、以下の基準で判断してください。
要素数が固定されており、メモリパフォーマンスを極限まで高めたい場合は配列を選択します。
一方、要素の追加や削除が頻繁に発生し、サイズが予測できない場合はList<T>を使用するのが一般的です。
実務ではList<T>の方が柔軟性が高いため多用されますが、内部的には配列が使われていることを理解しておくと深い知識に繋がります。
配列を使用する際のベストプラクティス
安全で効率的なコードを書くために、以下のポイントを意識してください。
まず、マジックナンバーを避けることが大切です。
配列のサイズを指定する際は、直接「5」などの数値を書くのではなく、定数や変数を使用しましょう。
次に、配列をメソッドの戻り値として返す場合は、空の配列(Array.Empty<T>())を返すようにし、nullを返さないようにするのが良いマナーです。
これにより、呼び出し側でのnullチェックを省略でき、プログラムの堅牢性が向上します。
まとめ
C#の配列は、データの基本単位として非常に重要な役割を担っています。
本記事では、基本的な宣言方法から、コレクション式、Index/Rangeによる操作、そしてパフォーマンスに優れたSpanの活用までを解説しました。
配列の特性を理解し、適切に使い分けることで、アプリケーションの動作速度やメモリ効率を劇的に向上させることが可能です。
特に2026年現在のモダンな開発環境では、簡潔な構文と効率的なメモリ管理の両立が求められます。
今回学んだテクニックを実際のプロジェクトで活用し、より洗練されたC#プログラムを構築していきましょう。
配列をマスターすることは、C#プログラマーとして一段上のステップへ進むための大きな足がかりとなるはずです。
