C#配列の初期化方法まとめ|基本構文から省略形・多次元配列までわかりやすく解説

はじめに

C#で複数の値をまとめて扱いたいときに使う代表的な仕組みが「配列」です。配列を使うと、数値、文字列、真偽値、オブジェクトなど、同じ型のデータをひとまとまりとして管理できます。

一方で、C#の配列初期化にはいくつかの書き方があります。

C#
int[] numbers = new int[3];

int[] scores = new int[] { 80, 90, 100 };

int[] values = { 1, 2, 3 };

var ids = new[] { 10, 20, 30 };

どれも配列を作るコードですが、「要素数だけ指定するのか」「値も同時に入れるのか」「型やnewを省略できるのか」によって使い分けが必要です。

この記事では、C#配列の初期化方法を基本構文から省略形、多次元配列、ジャグ配列、C# 12以降のコレクション式までわかりやすく解説します。配列初期化でよくあるエラーや、Listとの違いもあわせて紹介するので、C#初心者の方でも実践的に理解できます。

1. C#の配列初期化とは

C#の配列初期化とは、配列を作成し、必要に応じて各要素に初期値を設定することです。

配列は、同じ型の複数の値をまとめて扱うためのデータ構造です。たとえば、テストの点数を複数保存したい場合、次のように配列を使えます。C#の配列は、要素の型を指定して宣言することで、同じ型の複数の変数を1つのデータ構造として扱えます。Microsoft Learn

C#
int[] scores = { 80, 90, 75, 100 };

このコードでは、int型の値を4つ持つ配列を初期化しています。

1-1. 配列の初期化でできること

配列の初期化では、主に次のようなことができます。

C#
int[] numbers = new int[5];

このように書くと、要素数5のint配列を作成できます。値を明示的に指定していないため、各要素にはint型の既定値である0が入ります。

値を最初から指定したい場合は、次のように書きます。

C#
int[] numbers = new int[] { 1, 2, 3, 4, 5 };

また、省略形を使うと、より短く書けます。

C#
int[] numbers = { 1, 2, 3, 4, 5 };

配列初期化では、「配列のサイズだけを決める」「配列の値も同時に決める」「空の配列を作る」「多次元配列を作る」といった処理ができます。

1-2. 配列の宣言・生成・代入の違い

C#の配列を理解するうえで、「宣言」「生成」「代入」の違いを押さえておくことが重要です。

宣言は、配列変数を用意することです。

C#
int[] numbers;

この時点では、numbersという配列変数はありますが、配列そのものはまだ作られていません。

生成は、newを使って配列の実体を作ることです。

C#
numbers = new int[3];

これで、要素数3のint配列が作成され、numbersから参照できるようになります。

代入は、配列の要素に値を入れることです。

C#
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;

宣言・生成・代入をまとめて書くこともできます。

C#
int[] numbers = new int[] { 10, 20, 30 };

さらに短く書くと、次のようになります。

C#
int[] numbers = { 10, 20, 30 };

このように、C#の配列初期化では、宣言・生成・代入を分けて書くことも、一度にまとめて書くこともできます。

1-3. 配列を初期化しない場合の既定値

配列を要素数だけ指定して作成した場合、各要素には型ごとの既定値が入ります。

C#
int[] numbers = new int[3];

Console.WriteLine(numbers[0]); // 0
Console.WriteLine(numbers[1]); // 0
Console.WriteLine(numbers[2]); // 0

int配列では、各要素の既定値は0です。

bool配列の場合はfalseになります。

C#
bool[] flags = new bool[3];

Console.WriteLine(flags[0]); // False

stringなどの参照型配列では、各要素の既定値はnullです。

C#
string[] names = new string[3];

Console.WriteLine(names[0] == null); // True

つまり、配列そのものをnewで作成していれば、各要素は自動的に既定値で初期化されます。ただし、参照型の配列では各要素がnullになるため、要素を使う前に値を代入する必要があります。

2. C#配列の基本的な初期化方法

C#配列の基本的な初期化方法は、大きく分けて「要素数を指定する方法」と「値を指定する方法」があります。

2-1. 要素数を指定して初期化する方法

要素数を指定して配列を初期化するには、次のように書きます。

C#
int[] numbers = new int[5];

このコードでは、5個のint値を格納できる配列を作成しています。インデックスは0から始まるため、アクセスできる範囲はnumbers[0]からnumbers[4]までです。

C#
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;

要素数を超えたインデックスにアクセスすると、実行時エラーになります。

C#
numbers[5] = 60; // エラー

配列の要素数は、作成時に固定されます。そのため、後から要素数を増やしたい場合は、新しい配列を作成するか、List<T>を使うのが一般的です。

2-2. 値を指定して初期化する方法

配列の作成と同時に値を指定する場合は、次のように書きます。

C#
int[] numbers = new int[] { 10, 20, 30 };

この場合、配列の要素数は初期値の数から自動的に決まります。上記の例では、値が3つあるため、要素数3の配列になります。

文字列配列でも同じように書けます。

C#
string[] fruits = new string[] { "Apple", "Banana", "Orange" };

この書き方は、どの型の配列を作っているのかが明確です。初心者のうちは、まずこの基本形を覚えておくとよいでしょう。

2-3. 宣言と同時に初期化する方法

C#では、配列の宣言と同時に初期化する場合、newを省略できます。

C#
int[] numbers = { 1, 2, 3 };

これは次のコードと同じ意味です。

C#
int[] numbers = new int[] { 1, 2, 3 };

文字列配列でも同じです。

C#
string[] names = { "佐藤", "鈴木", "田中" };

この省略形はよく使われます。コードが短くなり、読みやすいからです。

ただし、この省略形は「宣言と同時に初期化する場合」に使える書き方です。宣言後に代入する場合は、newを省略できません。

2-4. 宣言後に配列を初期化する方法

配列変数を先に宣言し、後から配列を初期化することもできます。

C#
int[] numbers;

numbers = new int[] { 1, 2, 3 };

この書き方は問題ありません。

一方で、次のように書くことはできません。

C#
int[] numbers;

numbers = { 1, 2, 3 }; // エラー

{ 1, 2, 3 }だけでは、後から代入する配列初期化式として使えません。宣言後に初期化する場合は、次のようにnew int[]を付ける必要があります。

C#
numbers = new int[] { 1, 2, 3 };

この違いは、C#配列初期化で初心者がつまずきやすいポイントです。

3. C#配列初期化の省略形

C#では、配列初期化を簡潔に書くための省略形が用意されています。省略形を正しく使えるようになると、コードがすっきりして読みやすくなります。

3-1. newを省略した配列初期化

宣言と同時に配列を初期化する場合、new 型[]を省略できます。

C#
int[] numbers = { 1, 2, 3 };

これは次の書き方と同じです。

C#
int[] numbers = new int[] { 1, 2, 3 };

string配列でも同様です。

C#
string[] colors = { "Red", "Green", "Blue" };

この書き方はシンプルで、実務でもよく使われます。ただし、宣言後に代入するときは使えない点に注意しましょう。

3-2. 型推論を使った配列初期化

C#では、new[]を使うことで、配列の型をコンパイラに推論させることができます。

C#
int[] numbers = new[] { 1, 2, 3 };

この場合、123はすべてintなので、int[]として推論されます。

C#
string[] names = new[] { "Alice", "Bob", "Charlie" };

この場合は、string[]として推論されます。

ただし、型が混在している場合は注意が必要です。

C#
var values = new[] { 1, 2, 3 }; // int[]

これは問題ありません。

C#
var mixed = new[] { 1, "text" }; // エラー

intstringが混在しているため、共通の配列型を推論できずエラーになります。混在させたい場合は、明示的にobject[]を使います。

C#
object[] mixed = { 1, "text", true };

3-3. varとnew[]を使う書き方

varnew[]を組み合わせると、左辺の型も省略できます。

C#
var numbers = new[] { 1, 2, 3 };

この場合、numbersint[]として扱われます。

C#
var fruits = new[] { "Apple", "Banana", "Orange" };

この場合、fruitsstring[]です。

varを使うとコードは短くなりますが、読み手が型をすぐに判断できない場合もあります。そのため、型を明確に見せたい場面では、次のように明示的に書くほうが読みやすいこともあります。

C#
string[] fruits = { "Apple", "Banana", "Orange" };

varは便利ですが、配列の型がわかりにくくなる場合は使いすぎに注意しましょう。

3-4. 空の配列を初期化する書き方

空の配列を作る方法はいくつかあります。

C#
int[] empty1 = new int[0];

また、値を指定しない初期化式を使って次のようにも書けます。

C#
int[] empty2 = new int[] { };

より推奨されることが多いのは、Array.Empty<T>()を使う方法です。

C#
int[] empty3 = Array.Empty<int>();

Array.Empty<T>()は、指定した型の空配列を返すメソッドです。Microsoft Learnでも、Array.Empty<T>()は空の配列を返すメソッドとして説明されています。Microsoft Learn

C# 12以降では、ターゲット型がわかる場面で次のような書き方もできます。

C#
int[] empty4 = [];

この書き方については、後ほど「C# 12以降のコレクション式」で詳しく解説します。

4. データ型別の配列初期化例

配列初期化の考え方はどの型でも基本的に同じですが、型によって既定値や注意点が異なります。

4-1. int配列の初期化

int配列は、数値データを扱うときによく使います。

C#
int[] scores = new int[3];

この場合、各要素は0で初期化されます。

C#
Console.WriteLine(scores[0]); // 0

値を指定して初期化する場合は、次のように書きます。

C#
int[] scores = { 80, 90, 100 };

合計や平均を計算する場合にも便利です。

C#
int total = 0;

for (int i = 0; i < scores.Length; i++)
{
total += scores[i];
}

double average = (double)total / scores.Length;

Console.WriteLine(average);

4-2. string配列の初期化

string配列は、名前や商品名、カテゴリ名など、文字列の一覧を扱うときに使います。

C#
string[] names = new string[3];

この場合、各要素の既定値はnullです。

C#
Console.WriteLine(names[0] == null); // True

値を指定して初期化する場合は、次のように書きます。

C#
string[] names = { "佐藤", "鈴木", "田中" };

文字列配列を順番に表示する例です。

C#
foreach (string name in names)
{
Console.WriteLine(name);
}

stringは参照型なので、要素を使う前にnullでないか確認したほうが安全な場合があります。

4-3. bool配列の初期化

bool配列は、オン・オフ、完了・未完了、表示・非表示などの状態を管理するときに使えます。

C#
bool[] flags = new bool[3];

この場合、各要素はfalseで初期化されます。

C#
Console.WriteLine(flags[0]); // False

値を指定する場合は、次のように書きます。

C#
bool[] flags = { true, false, true };

条件判定に使う例です。

C#
if (flags[0])
{
Console.WriteLine("有効です");
}

4-4. object配列の初期化

object配列を使うと、異なる型の値を同じ配列に格納できます。C#では、定義済み型、ユーザー定義型、参照型、値型を含むすべての型が直接または間接的にObjectを継承するため、object型の配列にはさまざまな値を格納できます。Microsoft Learn

C#
object[] values = { 1, "text", true, 3.14 };

ただし、取り出した値はobject型として扱われるため、元の型として使うにはキャストや型チェックが必要です。

C#
object value = values[0];

if (value is int number)
{
Console.WriteLine(number + 10);
}

object[]は便利ですが、型安全性が下がります。特別な理由がない限り、int[]string[]のように具体的な型の配列を使うほうがよいでしょう。

4-5. クラスや構造体の配列初期化

クラスの配列を作る場合、配列を作成しただけでは各要素のインスタンスは作成されません。

C#
Person[] people = new Person[3];

この場合、people[0]people[1]people[2]はすべてnullです。

C#
people[0] = new Person { Name = "佐藤" };
people[1] = new Person { Name = "鈴木" };
people[2] = new Person { Name = "田中" };

クラス配列を値付きで初期化する例です。

C#
Person[] people =
{
new Person { Name = "佐藤", Age = 30 },
new Person { Name = "鈴木", Age = 25 },
new Person { Name = "田中", Age = 28 }
};

class Person
{
public string Name { get; set; } = "";
public int Age { get; set; }
}

構造体の場合は、各要素が既定値で初期化されます。

C#
Point[] points = new Point[2];

Console.WriteLine(points[0].X); // 0
Console.WriteLine(points[0].Y); // 0

struct Point
{
public int X;
public int Y;
}

構造体配列も、値を指定して初期化できます。

C#
Point[] points =
{
new Point { X = 10, Y = 20 },
new Point { X = 30, Y = 40 }
};

5. 多次元配列・ジャグ配列の初期化

C#では、通常の1次元配列だけでなく、多次元配列やジャグ配列も使えます。表形式のデータや行列のようなデータを扱うときに便利です。

5-1. 2次元配列の初期化方法

2次元配列は、行と列を持つ配列です。

C#
int[,] matrix = new int[2, 3];

このコードでは、2行3列のint配列を作成しています。

値を代入する場合は、次のように行と列のインデックスを指定します。

C#
matrix[0, 0] = 1;
matrix[0, 1] = 2;
matrix[0, 2] = 3;
matrix[1, 0] = 4;
matrix[1, 1] = 5;
matrix[1, 2] = 6;

初期値をまとめて指定することもできます。

C#
int[,] matrix =
{
{ 1, 2, 3 },
{ 4, 5, 6 }
};

この配列は、次のようなイメージです。

1 2 3
4 5 6

2次元配列の要素にアクセスするには、次のように書きます。

C#
Console.WriteLine(matrix[0, 1]); // 2
Console.WriteLine(matrix[1, 2]); // 6

5-2. 3次元配列の初期化方法

3次元配列は、奥行きを持つ配列です。使う機会は2次元配列より少ないですが、立体的なデータや複数の表をまとめて扱う場合に使えます。

C#
int[,,] cube = new int[2, 2, 2];

値を指定して初期化する例です。

C#
int[,,] cube =
{
{
{ 1, 2 },
{ 3, 4 }
},
{
{ 5, 6 },
{ 7, 8 }
}
};

アクセスするときは、3つのインデックスを指定します。

C#
Console.WriteLine(cube[0, 0, 0]); // 1
Console.WriteLine(cube[1, 1, 1]); // 8

3次元配列は構造が複雑になりやすいため、実務ではクラスやList、辞書など別のデータ構造を検討したほうが読みやすい場合もあります。

5-3. ジャグ配列の初期化方法

ジャグ配列は、「配列の配列」です。2次元配列のように見えますが、各行の長さを変えられる点が特徴です。

C#
int[][] jagged = new int[3][];

このコードでは、3つの配列を格納できる配列を作成しています。ただし、内側の配列はまだ作成されていません。

C#
jagged[0] = new int[] { 1, 2 };
jagged[1] = new int[] { 3, 4, 5 };
jagged[2] = new int[] { 6 };

宣言と同時に初期化する場合は、次のように書けます。

C#
int[][] jagged =
{
new int[] { 1, 2 },
new int[] { 3, 4, 5 },
new int[] { 6 }
};

アクセスするときは、インデックスを2回指定します。

C#
Console.WriteLine(jagged[0][1]); // 2
Console.WriteLine(jagged[1][2]); // 5

2次元配列はmatrix[0, 1]のようにカンマで指定しますが、ジャグ配列はjagged[0][1]のように角かっこを分けて指定します。

5-4. 多次元配列とジャグ配列の違い

多次元配列とジャグ配列の大きな違いは、構造です。

多次元配列は、行と列が固定された長方形のような配列です。

C#
int[,] matrix =
{
{ 1, 2, 3 },
{ 4, 5, 6 }
};

この場合、各行の要素数は同じです。

一方、ジャグ配列は配列の中に配列を入れる構造です。

C#
int[][] jagged =
{
new int[] { 1, 2 },
new int[] { 3, 4, 5 },
new int[] { 6 }
};

この場合、各行の要素数を変えられます。

Microsoft Learnのインデックスと範囲に関する説明でも、多次元配列は複数のパラメーターを持つインデクサーを使い、ジャグ配列は配列の配列としてインデックス操作できることが示されています。Microsoft Learn

使い分けの目安は次のとおりです。

C#
// 行と列の数が固定されている表形式データ
int[,] matrix = new int[2, 3];

// 行ごとに要素数が違うデータ
int[][] jagged = new int[3][];

行と列がきれいにそろうデータなら多次元配列、行ごとに長さが変わるデータならジャグ配列を使うとよいでしょう。

6. 配列初期化後の値の代入・変更

配列は初期化したあとでも、各要素の値を変更できます。ただし、配列の要素数そのものは変更できません。

6-1. インデックスを指定して値を代入する方法

配列の要素を変更するには、インデックスを指定します。

C#
int[] numbers = new int[3];

numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;

既に値が入っている配列でも、同じように変更できます。

C#
int[] numbers = { 1, 2, 3 };

numbers[1] = 100;

Console.WriteLine(numbers[1]); // 100

インデックスは0から始まります。そのため、要素数3の配列で使えるインデックスは012です。

C#
int[] numbers = { 1, 2, 3 };

Console.WriteLine(numbers[0]); // 1
Console.WriteLine(numbers[2]); // 3

6-2. for文を使って配列を初期化する方法

同じルールで配列に値を入れたい場合は、for文を使うと便利です。

C#
int[] numbers = new int[5];

for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = i + 1;
}

このコードでは、配列に1から5までの値を代入しています。

C#
foreach (int number in numbers)
{
Console.WriteLine(number);
}

出力結果は次のようになります。

1
2
3
4
5

配列の要素数はLengthプロパティで取得できます。

C#
int count = numbers.Length;

for文とLengthを組み合わせると、配列のサイズが変わっても安全にループできます。

6-3. foreachでは配列要素を直接変更できない理由

foreachは、配列やコレクションの要素を順番に取り出して処理するための構文です。Microsoft Learnでも、foreach文はコレクションの要素を列挙し、各要素に対して本文を実行する構文として説明されています。Microsoft Learn

C#
int[] numbers = { 1, 2, 3 };

foreach (int number in numbers)
{
Console.WriteLine(number);
}

ただし、foreachのループ変数に値を代入しても、配列の要素を直接変更することはできません。

C#
int[] numbers = { 1, 2, 3 };

foreach (int number in numbers)
{
// number = 10; // エラー
}

foreachのループ変数は読み取り用として扱われるため、値を変更できません。

配列の要素を変更したい場合は、for文を使います。

C#
int[] numbers = { 1, 2, 3 };

for (int i = 0; i < numbers.Length; i++)
{
numbers[i] *= 2;
}

このように、配列の中身を書き換える処理ではfor文、値を読み取るだけならforeachを使うと考えるとわかりやすいです。

6-4. Array.Fillを使って同じ値で初期化する方法

配列のすべての要素に同じ値を入れたい場合は、Array.Fillを使うと便利です。Array.Fill<T>(T[] array, T value)は、指定した配列の各要素に指定した値を代入するメソッドです。Microsoft Learn

C#
int[] numbers = new int[5];

Array.Fill(numbers, 100);

この結果、配列のすべての要素が100になります。

C#
foreach (int number in numbers)
{
Console.WriteLine(number);
}

出力結果は次のとおりです。

100
100
100
100
100

一部の範囲だけを同じ値で埋めることもできます。

C#
int[] numbers = { 1, 2, 3, 4, 5 };

Array.Fill(numbers, 0, 1, 3);

この場合、インデックス1から3個分の要素が0になります。

C#
// 結果: { 1, 0, 0, 0, 5 }

同じ値で配列をまとめて初期化したい場合は、for文よりもArray.Fillのほうが意図を伝えやすいことがあります。

7. 空配列・null配列の扱い方

C#で配列を扱うときは、「空配列」と「null配列」の違いを理解しておくことが大切です。この違いを理解していないと、NullReferenceExceptionの原因になります。

7-1. 空配列とnullの違い

空配列とは、要素数が0の配列です。

C#
int[] empty = new int[0];

または、次のように書けます。

C#
int[] empty = Array.Empty<int>();

空配列は、配列の実体が存在しています。ただし、要素数が0です。

C#
Console.WriteLine(empty.Length); // 0

一方、null配列は、配列の実体そのものが存在しません。

C#
int[]? numbers = null;

この状態でLengthにアクセスすると、例外が発生します。

C#
Console.WriteLine(numbers.Length); // NullReferenceException

空配列は「要素がない配列」、nullは「配列が存在しない状態」と考えるとわかりやすいです。

7-2. Array.Emptyを使った空配列の初期化

空配列を表す場合は、Array.Empty<T>()を使うのがおすすめです。

C#
string[] names = Array.Empty<string>();

Array.Empty<T>()は空の配列を返すため、要素がない状態を安全に表現できます。Microsoft Learn

C#
foreach (string name in names)
{
Console.WriteLine(name);
}

空配列に対するforeachは、単に1回も実行されません。nullのように例外が発生するわけではありません。

メソッドの戻り値としても、nullより空配列を返すほうが扱いやすいことが多いです。

C#
string[] GetNames()
{
return Array.Empty<string>();
}

呼び出し側は、nullチェックをせずにループできます。

C#
foreach (string name in GetNames())
{
Console.WriteLine(name);
}

7-3. null参照例外を防ぐ初期化の考え方

NullReferenceExceptionを防ぐには、配列変数をできるだけnullにしないことが大切です。

よくない例です。

C#
string[]? names = null;

foreach (string name in names)
{
Console.WriteLine(name);
}

このコードは、namesnullのため例外になります。

空配列で初期化しておけば、安全に扱えます。

C#
string[] names = Array.Empty<string>();

foreach (string name in names)
{
Console.WriteLine(name);
}

条件によって配列を設定する場合も、初期値を空配列にしておくと安全です。

C#
string[] names = Array.Empty<string>();

if (DateTime.Now.DayOfWeek == DayOfWeek.Monday)
{
names = new[] { "佐藤", "鈴木" };
}

このようにしておけば、条件を満たさない場合でもnamesnullになりません。

7-4. 空配列を使うべきケース

空配列は、次のような場面で使うと便利です。

C#
string[] GetErrors()
{
return Array.Empty<string>();
}

エラーがない場合にnullではなく空配列を返すと、呼び出し側の処理がシンプルになります。

C#
string[] errors = GetErrors();

if (errors.Length == 0)
{
Console.WriteLine("エラーはありません");
}

検索結果が0件の場合にも空配列が向いています。

C#
Product[] SearchProducts(string keyword)
{
return Array.Empty<Product>();
}

「結果がない」ことを表したいだけなら、nullより空配列のほうが安全です。

ただし、「まだ読み込んでいない」「データが存在するかどうか不明」といった状態を区別したい場合は、nullや別の状態管理を使うこともあります。

8. C# 12以降のコレクション式による配列初期化

C# 12以降では、コレクション式を使って配列をより簡潔に初期化できます。コレクション式は、配列やコレクションの初期値を短く書ける構文です。Microsoft Learnでも、C# 12の新機能としてコレクション式が紹介されており、コレクション要素の初期値指定や、コレクション型を受け取るメソッドへの引数として使用できると説明されています。Microsoft Learn

8-1. []を使った空配列の初期化

C# 12以降では、ターゲット型が明確な場合、[]で空配列を初期化できます。

C#
int[] numbers = [];

これは、空のint配列を表します。

C#
string[] names = [];

このコードでは、空のstring配列を初期化しています。

従来の書き方と比べると、かなり短く書けます。

C#
int[] numbers1 = new int[0];
int[] numbers2 = Array.Empty<int>();
int[] numbers3 = [];

Microsoft Learnのコレクション式の説明では、空のコレクション式[]は、ターゲットが初期化後に変更されない場合などにArray.Empty<T>()として実現されることがあると説明されています。Microsoft Learn

8-2. [1, 2, 3]を使った配列初期化

C# 12以降では、値を指定した配列初期化も次のように書けます。

C#
int[] numbers = [1, 2, 3];

文字列配列も同様です。

C#
string[] names = ["佐藤", "鈴木", "田中"];

これは、従来の次の書き方に近い意味です。

C#
int[] numbers = { 1, 2, 3 };

または、

C#
int[] numbers = new int[] { 1, 2, 3 };

コレクション式は、配列だけでなく、List<T>などのコレクション初期化にも使えます。C#のコレクションに関する公式ドキュメントでも、C# 12からコレクション型をコレクション式で初期化できることが説明されています。Microsoft Learn

C#
List<int> numbers = [1, 2, 3];

配列にもListにも似た形で書けるため、コードの見た目を統一しやすくなります。

8-3. 従来の配列初期化との違い

従来の配列初期化では、次のように書きます。

C#
int[] numbers = { 1, 2, 3 };

C# 12以降のコレクション式では、次のように書きます。

C#
int[] numbers = [1, 2, 3];

見た目の違いは、波かっこ{}を使うか、角かっこ[]を使うかです。

従来の省略形は、主に配列の初期化で使われます。

C#
int[] numbers = { 1, 2, 3 };

一方、コレクション式は、配列だけでなく、Listなどのコレクションにも使えるのが特徴です。

C#
int[] array = [1, 2, 3];

List<int> list = [1, 2, 3];

ただし、コレクション式を使うには、プロジェクトがC# 12以降に対応している必要があります。古いC#バージョンではコンパイルエラーになります。

8-4. 使用できるC#バージョンの確認ポイント

コレクション式を使う場合は、C#の言語バージョンを確認しましょう。

.csprojで言語バージョンを指定している場合は、次のような設定を確認します。

XML
<PropertyGroup>
<LangVersion>12.0</LangVersion>
</PropertyGroup>

または、最新のメジャーバージョンを使う設定にしている場合もあります。

XML
<PropertyGroup>
<LangVersion>latest</LangVersion>
</PropertyGroup>

C# 12の機能を使うには、対応する.NET SDKや開発環境が必要です。プロジェクトやチームで古いバージョンを使っている場合は、従来の配列初期化構文を使ったほうが安全です。

C#
// 古いC#でも使いやすい
int[] numbers = { 1, 2, 3 };

// C# 12以降
int[] values = [1, 2, 3];

学習目的であれば、まず従来の配列初期化を理解し、そのうえでC# 12以降のコレクション式を覚えるとよいでしょう。

9. 配列初期化でよくあるエラーと対処法

C#の配列初期化では、書き方を少し間違えるだけでコンパイルエラーや実行時エラーになることがあります。ここでは、初心者がつまずきやすいエラーを紹介します。

9-1. 要素数と初期値の指定で起きるエラー

次のように、要素数と初期値を同時に指定する書き方はできません。

C#
int[] numbers = new int[3] { 1, 2, 3 };

このコードは一見正しそうに見えますが、C#では配列初期化子を使う場合、要素数を明示しない形にするのが基本です。

正しくは次のように書きます。

C#
int[] numbers = new int[] { 1, 2, 3 };

または省略形を使います。

C#
int[] numbers = { 1, 2, 3 };

要素数だけ指定する場合は、初期値を書きません。

C#
int[] numbers = new int[3];

値を指定する場合は、値の数から要素数が決まると覚えておきましょう。

9-2. 型が一致しない場合のエラー

配列には、基本的に同じ型の値を入れる必要があります。

C#
int[] numbers = { 1, 2, "3" }; // エラー

"3"は文字列なので、int[]には入れられません。

正しくは、すべて数値にします。

C#
int[] numbers = { 1, 2, 3 };

文字列として扱いたいなら、string[]にします。

C#
string[] numbers = { "1", "2", "3" };

複数の型を混在させたい場合は、object[]を使います。

C#
object[] values = { 1, "text", true };

ただし、object[]は型安全性が低くなるため、必要な場合だけ使いましょう。

9-3. null配列にアクセスしたときのエラー

配列変数がnullの状態で要素やLengthにアクセスすると、NullReferenceExceptionが発生します。

C#
int[]? numbers = null;

Console.WriteLine(numbers.Length); // NullReferenceException

対処法としては、空配列で初期化する方法があります。

C#
int[] numbers = Array.Empty<int>();

Console.WriteLine(numbers.Length); // 0

また、nullの可能性がある場合は、事前にチェックします。

C#
int[]? numbers = null;

if (numbers != null)
{
Console.WriteLine(numbers.Length);
}

null条件演算子を使うこともできます。

C#
Console.WriteLine(numbers?.Length ?? 0);

配列を戻り値にするメソッドでは、可能であればnullではなく空配列を返すと、呼び出し側のコードが安全になります。

9-4. 多次元配列の初期化で間違いやすい書き方

2次元配列では、各行の要素数をそろえる必要があります。

C#
int[,] matrix =
{
{ 1, 2 },
{ 3, 4, 5 } // エラー
};

多次元配列は長方形の構造なので、行ごとに要素数を変えられません。

正しくは、次のように要素数をそろえます。

C#
int[,] matrix =
{
{ 1, 2, 0 },
{ 3, 4, 5 }
};

行ごとに要素数を変えたい場合は、ジャグ配列を使います。

C#
int[][] jagged =
{
new int[] { 1, 2 },
new int[] { 3, 4, 5 }
};

また、2次元配列とジャグ配列ではアクセス方法も違います。

C#
int[,] matrix =
{
{ 1, 2 },
{ 3, 4 }
};

Console.WriteLine(matrix[0, 1]); // 2
C#
int[][] jagged =
{
new int[] { 1, 2 },
new int[] { 3, 4, 5 }
};

Console.WriteLine(jagged[0][1]); // 2

[,][][]は似ていますが、まったく別の配列構造です。

10. 配列初期化とList初期化の違い

C#では、複数のデータを扱う方法として配列のほかにList<T>もよく使われます。どちらも複数の値を管理できますが、特徴が異なります。

10-1. 配列を使うべきケース

配列は、要素数が固定されている場合に向いています。

C#
int[] scores = { 80, 90, 100 };

たとえば、曜日、月、固定件数の設定値など、要素数が変わらないデータに適しています。

C#
string[] days =
{
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
};

また、APIやライブラリによっては配列を引数や戻り値として要求する場合があります。そのような場合も配列を使います。

配列はシンプルで、固定長のデータを扱うときにわかりやすい構造です。

10-2. Listを使うべきケース

List<T>は、要素数が後から増えたり減ったりする場合に向いています。

C#
List<int> numbers = new List<int>();

numbers.Add(10);
numbers.Add(20);
numbers.Add(30);

配列は作成後に要素数を変更できませんが、ListはAddRemoveを使って要素を追加・削除できます。

C#
numbers.Remove(20);

ユーザー入力、検索結果、データベースから取得した件数不定のデータなどは、Listで扱うほうが自然です。

C#
List<string> names = new List<string>();

names.Add("佐藤");
names.Add("鈴木");

要素数が変わる可能性があるなら、最初からListを使うと扱いやすくなります。

10-3. 配列とListの初期化構文の違い

配列の初期化は次のように書きます。

C#
int[] numbers = { 1, 2, 3 };

newを明示する場合は、次のようになります。

C#
int[] numbers = new int[] { 1, 2, 3 };

Listの初期化は、従来は次のように書きます。

C#
List<int> numbers = new List<int> { 1, 2, 3 };

コレクション初期化子を使うと、Addを何度も書かずに初期値を指定できます。Microsoft Learnでも、コレクション初期化子は、IEnumerableを実装し、適切なAddメソッドを持つコレクション型を初期化するときに、1つ以上の要素初期化子を指定できる構文として説明されています。Microsoft Learn

C# 12以降では、配列もListもコレクション式で初期化できます。

C#
int[] array = [1, 2, 3];

List<int> list = [1, 2, 3];

新しい構文を使うと、配列とListの初期化の見た目がかなり近くなります。

10-4. 配列からListへ変換する方法

配列をListに変換するには、ToList()を使います。

C#
using System.Linq;

int[] array = { 1, 2, 3 };

List<int> list = array.ToList();

また、Listのコンストラクターに配列を渡す方法もあります。

C#
int[] array = { 1, 2, 3 };

List<int> list = new List<int>(array);

逆に、Listから配列に変換するにはToArray()を使います。

C#
List<int> list = new List<int> { 1, 2, 3 };

int[] array = list.ToArray();

配列とListは相互に変換できるため、用途に応じて使い分けることができます。

11. C#配列初期化の実践コード例

ここでは、実際のプログラムで使いやすい配列初期化の例を紹介します。

11-1. 数値データを配列で初期化する例

テストの点数を配列で管理する例です。

C#
int[] scores = { 80, 90, 75, 100, 85 };

int total = 0;

for (int i = 0; i < scores.Length; i++)
{
total += scores[i];
}

double average = (double)total / scores.Length;

Console.WriteLine($"合計: {total}");
Console.WriteLine($"平均: {average}");

出力例です。

合計: 430
平均: 86

数値配列は、合計、平均、最大値、最小値などを計算するときによく使います。

LINQを使うと、さらに短く書けます。

C#
using System.Linq;

int[] scores = { 80, 90, 75, 100, 85 };

Console.WriteLine(scores.Sum());
Console.WriteLine(scores.Average());
Console.WriteLine(scores.Max());
Console.WriteLine(scores.Min());

11-2. 文字列一覧を配列で初期化する例

メニューやカテゴリの一覧を配列で管理する例です。

C#
string[] menus =
{
"ホーム",
"商品一覧",
"お問い合わせ",
"会社概要"
};

foreach (string menu in menus)
{
Console.WriteLine(menu);
}

条件に一致する文字列を探す例です。

C#
string[] fruits = { "Apple", "Banana", "Orange" };

string keyword = "Banana";

foreach (string fruit in fruits)
{
if (fruit == keyword)
{
Console.WriteLine("見つかりました");
}
}

文字列配列は、固定の選択肢やラベル一覧を扱うときに便利です。

11-3. 複数行データを2次元配列で初期化する例

表形式のデータを2次元配列で管理する例です。

C#
string[,] users =
{
{ "1", "佐藤", "東京" },
{ "2", "鈴木", "大阪" },
{ "3", "田中", "福岡" }
};

2次元配列を表示する例です。

C#
for (int row = 0; row < users.GetLength(0); row++)
{
for (int col = 0; col < users.GetLength(1); col++)
{
Console.Write(users[row, col] + " ");
}

Console.WriteLine();
}

出力例です。

1 佐藤 東京
2 鈴木 大阪
3 田中 福岡

2次元配列では、GetLength(0)で行数、GetLength(1)で列数を取得できます。

C#
int rowCount = users.GetLength(0);
int colCount = users.GetLength(1);

行と列が固定されているデータには、2次元配列が使いやすいです。

11-4. 条件に応じて配列を初期化する例

条件によって配列の中身を変えたい場合は、次のように書けます。

C#
bool isAdmin = true;

string[] menus;

if (isAdmin)
{
menus = new[] { "ユーザー管理", "設定", "ログ確認" };
}
else
{
menus = new[] { "マイページ", "お問い合わせ" };
}

三項演算子を使うと、より短く書けます。

C#
bool isAdmin = true;

string[] menus = isAdmin
? new[] { "ユーザー管理", "設定", "ログ確認" }
: new[] { "マイページ", "お問い合わせ" };

C# 12以降なら、コレクション式を使ってさらに簡潔に書けます。

C#
bool isAdmin = true;

string[] menus = isAdmin
? ["ユーザー管理", "設定", "ログ確認"]
: ["マイページ", "お問い合わせ"];

条件に応じて配列を切り替える場合も、nullではなく必ず何らかの配列を代入するようにすると安全です。

C#
string[] menus = Array.Empty<string>();

初期値として空配列を入れておけば、後続処理でnullチェックを減らせます。

12. C#配列初期化のよくある質問

C#配列の初期化について、よくある疑問をまとめます。

12-1. 配列の要素数は後から変更できるか

配列の要素数は、作成後に変更できません。

C#
int[] numbers = new int[3];

この配列は、要素数3で固定されます。

要素を追加したい場合は、新しい配列を作成してコピーする必要があります。

C#
int[] oldArray = { 1, 2, 3 };
int[] newArray = new int[4];

for (int i = 0; i < oldArray.Length; i++)
{
newArray[i] = oldArray[i];
}

newArray[3] = 4;

ただし、このような処理を自分で書くより、要素数が変わる場合はList<T>を使うほうが簡単です。

C#
List<int> numbers = new List<int> { 1, 2, 3 };

numbers.Add(4);

固定長なら配列、可変長ならListと考えるとよいでしょう。

12-2. 配列をすべて0で初期化する必要はあるか

int配列をnew int[要素数]で作成した場合、各要素は自動的に0になります。

C#
int[] numbers = new int[3];

Console.WriteLine(numbers[0]); // 0
Console.WriteLine(numbers[1]); // 0
Console.WriteLine(numbers[2]); // 0

そのため、すべての要素を明示的に0で代入する必要はありません。

C#
int[] numbers = new int[3];

// 基本的には不要
numbers[0] = 0;
numbers[1] = 0;
numbers[2] = 0;

ただし、コードの意図を明確にしたい場合や、既存の配列を再利用して値をリセットしたい場合は、Array.Fillを使うことがあります。

C#
Array.Fill(numbers, 0);

新しく作成したint配列であれば、自動的に0で初期化されると覚えておきましょう。

12-3. 空の配列はnewとArray.Emptyのどちらがよいか

空配列を作る方法として、次の2つがあります。

C#
int[] empty1 = new int[0];

int[] empty2 = Array.Empty<int>();

基本的には、Array.Empty<T>()を使うのがおすすめです。

C#
string[] names = Array.Empty<string>();

Array.Empty<T>()は空配列を返すメソッドで、空の結果を表すときに読みやすく、意図も明確です。Microsoft Learn

C# 12以降であれば、次の書き方も使えます。

C#
int[] empty = [];

ただし、チームやプロジェクトでC# 12を使えない場合は、Array.Empty<T>()を使うとよいでしょう。

12-4. 配列初期化の省略形は使っても問題ないか

配列初期化の省略形は、問題なく使えます。

C#
int[] numbers = { 1, 2, 3 };

この書き方は簡潔で読みやすく、よく使われます。

ただし、宣言後に代入する場合は使えません。

C#
int[] numbers;

// numbers = { 1, 2, 3 }; // エラー
numbers = new int[] { 1, 2, 3 };

また、型推論を使う場合は、配列の型がわかりにくくならないように注意しましょう。

C#
var numbers = new[] { 1, 2, 3 };

この程度であればint[]だとすぐにわかりますが、複雑な型では明示的に書いたほうが読みやすいこともあります。

C#
Customer[] customers =
{
new Customer { Name = "佐藤" },
new Customer { Name = "鈴木" }
};

省略形は便利ですが、「読みやすさ」を基準に使い分けることが大切です。

まとめ

C#の配列初期化には、さまざまな書き方があります。

基本形は、要素数を指定して初期化する方法です。

C#
int[] numbers = new int[3];

値を指定して初期化する場合は、次のように書きます。

C#
int[] numbers = new int[] { 1, 2, 3 };

宣言と同時に初期化するなら、省略形も使えます。

C#
int[] numbers = { 1, 2, 3 };

型推論を使った書き方もあります。

C#
var numbers = new[] { 1, 2, 3 };

空配列を初期化する場合は、Array.Empty<T>()が便利です。

C#
int[] empty = Array.Empty<int>();

C# 12以降では、コレクション式を使って次のようにも書けます。

C#
int[] numbers = [1, 2, 3];

int[] empty = [];

多次元配列やジャグ配列も、用途に応じて使い分けます。

C#
int[,] matrix =
{
{ 1, 2 },
{ 3, 4 }
};

int[][] jagged =
{
new int[] { 1, 2 },
new int[] { 3, 4, 5 }
};

C#配列の初期化で大切なのは、「配列の要素数は固定」「インデックスは0から始まる」「値を指定しない場合は既定値で初期化される」「空配列とnullは違う」という点です。

要素数が固定されているデータには配列、要素数が増減するデータにはListを使うと、コードがわかりやすくなります。まずは基本の配列初期化構文をしっかり覚え、必要に応じて省略形やC# 12以降のコレクション式も活用していきましょう。