C#というプログラミング言語は、長い歴史の中で常に進化を続けており、データの集合を扱う「配列」の操作も非常に洗練されてきました。
2026年現在の開発現場では、最新の.NET環境を活用した、より簡潔でパフォーマンスの高い記述方法が主流となっています。
本記事では、初心者が押さえておくべき基本的な初期化から、ベテランエンジニアも活用するモダンな「コレクション式」まで、幅広く解説します。
最適な初期化方法を選択することは、コードの可読性を高めるだけでなく、アプリケーションの実行効率を向上させるためにも非常に重要です。
C#における配列の基本と役割
C#における配列は、同じ型のデータを連続したメモリ領域に格納するための基本的なデータ構造です。
配列は一度作成するとそのサイズを変更できない「固定長」という特性を持っています。
この特性により、リストなどの可変長コレクションに比べてオーバーヘッドが少なく、メモリ効率に優れているというメリットがあります。
現代のC#開発では、List<T>などの動的コレクションが多用されますが、低レイヤーの処理やパフォーマンスが求められるシーンでは依然として配列が主役です。
配列を正しく初期化することは、バグを未然に防ぎ、保守しやすいプログラムを書くための第一歩となります。
配列を初期化する基本的な方法
まずは、C#で最も古くから使われている標準的な初期化方法について見ていきましょう。
サイズ指定のみを行う初期化
配列の要素数が決まっており、後から値を代入したい場合には、サイズを指定してインスタンスを生成します。
// 要素数5の整数型配列を生成
int[] numbers = new int[5];
この方法で初期化した場合、数値型であれば「0」、参照型であれば「null」といった、型の既定値(デフォルト値)で各要素が埋められます。
メモリ領域だけを先に確保しておきたい場合に、この書き方が選択されます。
宣言と同時に値を代入する初期化(初期化子)
宣言のタイミングで中身のデータが決まっている場合は、中括弧を用いた「配列初期化子」を使用します。
// 初期化子を使用して値を設定
string[] fruits = new string[] { "Apple", "Banana", "Orange" };
この書き方では、コンパイラが中括弧内の要素数を自動的に判断するため、要素数を明示的に書く必要はありません。
さらに省略した記法として、右辺の型指定を一部省くことも可能です。
// 型推論を利用した短い書き方
string[] names = { "田中", "佐藤", "鈴木" };
ただし、この省略記法は変数の宣言時のみ使用可能であり、既存の変数に再代入する際には使用できない点に注意が必要です。
型推論(var)を用いた初期化
C# 3.0から導入されたvarキーワードを使うことで、左辺の型宣言を省略できます。
// varキーワードによる型推論
var scores = new int[] { 90, 80, 70, 60 };
この場合、右辺の型情報から変数の型が決定されます。
varを使用する際は、右辺に必ず型名(new int[]など)を含める必要があります。
モダンなC#における配列初期化の進化
C# 12から導入された「コレクション式(Collection Expressions)」は、現在のC#開発における標準的な書き方となりました。
コレクション式(Collection Expressions)の活用
コレクション式を使用すると、new[]や{}を使わずに、角括弧だけで配列を表現できます。
// コレクション式による極めて簡潔な初期化
int[] numbers = [10, 20, 30, 40, 50];
この構文は非常に読みやすく、記述量も大幅に削減されるため、最新のプロジェクトでは最優先で検討すべき書き方です。
また、配列だけでなくList<T>やSpan<T>に対しても同じ構文が使えるため、コードの一貫性が保たれます。
スプレッド要素(Spread Element)による結合
コレクション式の中で、別の配列を展開して結合する「スプレッド要素(..)」も非常に便利です。
int[] firstHalf = [1, 2, 3];
int[] secondHalf = [4, 5, 6];
// 既存の配列を組み合わせて新しい配列を生成
int[] combined = [.. firstHalf, .. secondHalf, 7, 8];
combinedの内容: 1, 2, 3, 4, 5, 6, 7, 8
以前のようにConcatメソッドを使ったり、ループを回してコピーしたりする手間が省け、直感的に配列を合成できます。
特定の用途に合わせた配列生成
単純に値を並べるだけでなく、特定の規則に従って配列を生成したいケースも多いでしょう。
Array.Fillによる一括設定
特定の初期値ですべての要素を埋め尽くしたい場合は、Array.Fillメソッドが最適です。
var data = new int[100];
// 配列の全要素を「-1」で埋める
Array.Fill(data, -1);
これは、ループで一つずつ代入するよりもパフォーマンスが高く、コードの意図も明確になります。
Enumerable.RangeやRepeatの利用
LINQ(Language Integrated Query)を活用することで、連続した数値や同じ値の繰り返し配列を簡単に作成できます。
using System.Linq;
// 1から10までの連続した数値配列を生成
int[] sequence = Enumerable.Range(1, 10).ToArray();
// "Default"という文字列を5つ持つ配列を生成
string[] defaults = Enumerable.Repeat("Default", 5).ToArray();
テストデータの作成や、特定のアルゴリズムの初期値設定に非常に役立ちます。
パフォーマンスを意識した配列初期化
高負荷なシステムや、大量のデータを扱うアプリケーションでは、配列の初期化コストが無視できない場合があります。
ArrayPoolの活用
短時間だけ大量の配列を使い、すぐに破棄するような処理を繰り返すと、ガベージコレクション(GC)に負荷がかかります。
このような場面では、System.Buffers.ArrayPool<T>を利用して配列を「再利用」するのが一般的です。
using System.Buffers;
// プールから配列を借りる
int[] sharedArray = ArrayPool<int>.Shared.Rent(1024);
try
{
// 配列を使用した処理
sharedArray[0] = 100;
}
finally
{
// 使い終わったらプールへ返す
ArrayPool<int>.Shared.Return(sharedArray);
}
配列を新しく「作る」のではなく「借りる」という考え方は、大規模開発におけるパフォーマンスチューニングの鉄則です。
stackallocによるスタック割り当て
極めて高いパフォーマンスが求められ、かつ配列のサイズが非常に小さい場合は、stackallocを使用してヒープ領域ではなくスタック領域にメモリを確保できます。
// スタック上に領域を確保(Spanで安全に扱う)
Span<int> quickBuffer = stackalloc int[64];
スタックに確保されたメモリは、メソッドを抜けると自動的に解放されるため、GCの影響を受けません。
ただし、大きなサイズを確保しようとするとスタックオーバーフローを引き起こす危険があるため、利用には注意が必要です。
多次元配列とジャグ配列の初期化
C#には、行列のようなデータを扱うための「多次元配列」と、配列の中に配列を入れる「ジャグ配列」が存在します。
多次元配列(矩形配列)
すべての行の長さが等しい配列を「多次元配列」と呼びます。
// 2行3列の2次元配列
int[,] matrix = new int[2, 3] {
{ 1, 2, 3 },
{ 4, 5, 6 }
};
ジャグ配列(配列の配列)
行ごとに長さが異なる可能性がある配列を「ジャグ配列」と呼びます。
// 各行のサイズが異なる配列
int[][] jaggedArray = new int[3][];
jaggedArray[0] = [1, 2];
jaggedArray[1] = [3, 4, 5, 6];
jaggedArray[2] = [7];
モダンなC#では、ジャグ配列の各要素の初期化にもコレクション式を使用することで、非常に簡潔に記述できるようになりました。
初期化方法の比較まとめ
それぞれの初期化方法の特徴を以下の表にまとめました。
| 手法 | 構文例 | 主な用途 |
|---|---|---|
| サイズ指定 | new T[size] | サイズのみ確定しており、後から値を詰める場合 |
| 初期化子 | new[] { v1, v2 } | 古いバージョンのC#との互換性重視 |
| コレクション式 | [v1, v2] | 現在の推奨。最も簡潔で直感的 |
| Array.Fill | Array.Fill(arr, val) | すべての要素を同一の値で初期化する場合 |
| LINQ | Enumerable.Range(...) | 規則性のある数値を生成する場合 |
| ArrayPool | ArrayPool.Shared.Rent() | 高頻度な生成・破棄によるGC負荷を抑えたい場合 |
配列初期化時の注意点とベストプラクティス
配列を初期化する際には、いくつか注意すべきルールがあります。
まず、配列のインデックスは「0」から始まることを忘れてはいけません。
要素数5で初期化した配列の最大インデックスは「4」であり、これを超えてアクセスすると実行時エラーが発生します。
また、要素数が固定されるため、頻繁に要素を追加・削除する場合にはList<T>の使用を検討すべきです。
パフォーマンスを優先して配列を選択した場合は、可能な限り「読み取り専用」として扱うのが安全です。
内容を変更しない配列であれば、ReadOnlySpan<T>に代入することで、不慮の書き換えを防止し、最適化の恩恵を受けることができます。
まとめ
C#における配列の初期化は、言語の進化とともに驚くほどシンプルで強力なものへと変わってきました。
2026年現在の開発では、「コレクション式」をベースにしつつ、必要に応じて「ArrayPool」や「LINQ」を使い分けるのが賢明な判断です。
それぞれの書き方が持つメリットと、背後で動くメモリの仕組みを理解することで、より高品質なプログラムを作成できるはずです。
まずは基本の形をマスターし、状況に合わせた最適な初期化方法を選択できるようになりましょう。
日々のコーディングにおいて、本記事で紹介したモダンな書き方を積極的に取り入れてみてください。
