新人エンジニア研修で知っておきたい配列の作り方と使い方

なぜ、配列の理解が重要なのか、その理由

この記事では、当社の新人エンジニア研修の参考にC#を解説します。

前回は「繰り返し処理」について学びました。コンピュータの力を実感できたかと思います。
今回は配列の作成と使用について解説します。これまで学んだ通り、変数に値を格納して処理するのが基本でしたが、変数が10個、20個、100個… と増えてくると大変です。

そこで便利なのが配列です。配列とは「同じ型の複数の要素を並べて管理するデータ構造」です。C#では、インデックス(添字)を使って要素にアクセスします。

新人エンジニア
配列のイメージ

1. 配列の使い方

1) 配列を表す変数を宣言する

int[] ages;

  • int[] は「整数型(int)の配列」を表します。
  • ages は「intの配列型」の変数名です(まだ要素は確保していない)。

2) 配列の要素を確保する

ages = new int[3];

  • new int[3] で「要素数3のint配列」をヒープ(メモリ)に生成し、先頭の参照を返します。
  • この段階で ages[0], ages[1], ages[2] が使えます(初期値は 0)。
新人エンジニア
配列の初期値は0である

3) 添字(インデックス)を用いて要素に値を代入する

ages[0] = 10;
ages[1] = 20;
ages[2] = 51;


  • 配列インデックスは 0から開始 し、(要素数 - 1) が最大インデックスです。

4) 配列の要素を参照(読み出し)する

Console.WriteLine(ages[2]); // 51


  • ages[2] の値を取り出してコンソールに表示します。

サンプル:配列とfor

using System;

namespace Chap06
{
    public class Example01
    {
        public static void Main()
        {
            int[] ages;
            ages = new int[3];

            ages[0] = 10;
            ages[1] = 20;
            ages[2] = 51;

            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine(ages[i]);
            }
        }
    }
}

<実行結果>

10
20
51
  • 配列と繰り返し文は非常に相性が良いです。

配列の長さ Length

C#ではages.Length プロパティを使うことで、配列の要素数を取得できます。

for (int i = 0; i < ages.Length; i++)
{
    Console.WriteLine(ages[i]);
}

  • これにより、配列の要素数が変更されても自動的に対応できます(マジックナンバーの回避)。

配列の初期化リテラル

配列を一度に初期化する方法もあります。

int[] ages = { 10, 20, 51 };

  • この場合、要素数は 3 と自動的に確定します。

例題

以下の配列の場合、ages.lengthの値と最大の添字を答えなさい。

int[] ages = {10, 20, 51, 52, 53};
int[] ages = {10};


2. IndexOutOfRangeException

C#で、存在しない配列要素を指定すると IndexOutOfRangeException が発生します。

int[] ages = new int[3];
ages[3] = 10; // 配列は要素数3なので、有効インデックスは0~2のみ

<実行時エラー>

Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.

C#のコンパイラは、このエラーをコンパイル時には検出してくれません(チェック例外ではない)。実行時にインデックスが不正と判明して初めてエラーが出ます。


3. 参照とメモリのイメージ

ここまで ages[0], ages[1] などの要素に実際のデータが入ることを学びました。では、ages 自体には何が入っているのでしょうか?

C#ではクラスや配列は“参照型”

int[] ages = new int[3];
Console.WriteLine(ages);

を実行すると、C#ではたとえば System.Int32[] のような型情報が表示されるでしょう(環境により異なりますが、System.Int32[] とか System.Int32[3] などと表示する場合もあります)。

この中身は配列オブジェクトへの参照です。

スタック領域とヒープ領域(C#のイメージ)

  • スタック領域に配列変数agesが置かれる(内部にヒープ領域へのポインタ/参照を保持)
  • ヒープ領域に「要素数3のint配列」が確保される
  • ages は、ヒープ上にある配列オブジェクトを指し示す“参照”を保持します
  • ages[0], ages[1], ages[2] はヒープ内に確保された実際のデータです

イメージ図(簡略化):

[Stack]             [Heap]
 ages  ----->   [ int[3] ]
                0: 10
                1: 20
                2: 51


値型と参照型の違い

  • int, double, bool などの組み込み値型はスタック上に直接データを保持します。
  • 配列やクラスのインスタンスは参照型となり、変数にはオブジェクトの参照(アドレス)が入ります。

例題

以下の処理が行われると何が表示されますか?また、それはなぜですか?

int a = 1;
int b = a;
a = 2;
Console.WriteLine($"{a}:{b}");  // 出力は「2:1」

int[] a1 = { 1 };
int[] a2 = a1;
a1[0] = 2;
Console.WriteLine($"{a1[0]}:{a2[0]}");  // 出力はどうなる?


4. 配列の要素をまとめて表示する

配列の全要素を一度に出力したいとき、C#では以下の2つの方法があります。

方法1:string.Join を使う

using System;

namespace Chap06
{
    public class Example05
    {
        public static void Main()
        {
            int[] ages = { 10, 20, 51 };
            // 文字列化して出力
            Console.WriteLine(string.Join(", ", ages)); 
        }
    }
}

<実行結果>

10, 20, 51
  • string.Join は第1引数に区切り文字、第2引数に配列を渡すと「10, 20, 51」のような文字列を生成します。

方法2:次のforeach 文を使う


5. foreach

foreach 文は配列などの列挙可能なオブジェクトに対して、先頭から末尾まで自動で繰り返してくれます。

foreach (型 変数 in 配列)

using System;

namespace Chap06
{
    public class Example06
    {
        public static void Main()
        {
            int[] ages = { 10, 20, 51 };

            foreach (int age in ages)
            {
                Console.WriteLine(age);
            }
        }
    }
}

<実行結果>

10
20
51

注意:age は「一時変数」

foreach (int age in ages)
{
    age *= 2; 
}

このように一時変数ageに新たな値を代入しても、もとの配列内容は変わりません。C#では age は配列要素のコピーに過ぎず、配列自体の要素を書き換えているわけではありません。

  • メリット: インデックス管理をせずに書けるため、IndexOutOfRangeException のリスク減
  • 制限: 先頭から順にしか処理できず、要素を飛ばして走査したり、逆順で走査したりするには工夫が必要
  • 適用範囲: 配列やList<T>などのコレクションに対して使えます(C#のイテレーション方式)。

例題

次のfor文の繰り返し回数を答えなさい。

int[] a = new int[3] { 0, 1, 2 };
foreach (int i in a) { }   // 繰り返し回数は?

int[] b = { 1, 2, 3, 4, 5 };
foreach (int i in b) { }  // 繰り返し回数は?

char[] c = { 'A', 'B', 'C', 'D' };
foreach (char d in c) { } // 繰り返し回数は?


6. 多次元配列(2次元配列の例)

C#でも2次元以上の多次元配列を扱うことができます。見た目は行列のようですが、実際はいくつかの方法があります。ここでは「配列の配列」(ジャグ配列)か「本当の多次元配列」かによって使い方が少し異なります。

6-1. ジャグ配列(Jagged Array)

C#で int[][] scores = new int[][] { ... }; のように書くと「配列の配列」が作れます。長さの異なる配列を持つことも可能です。ジャグ配列といいます。

using System;

namespace Chap06
{
    public class Example08
    {
        public static void Main()
        {
            int[][] scores = {
                new int[] { 10, 20, 30, 40 },
                new int[] { 50, 60, 70, 80 },
                new int[] { 90, 10, 20, 30 }
            };

            Console.WriteLine(scores[0][3]); // 40
            Console.WriteLine(scores[2][3]); // 30

            // 二重の foreach
            foreach (int[] row in scores)
            {
                foreach (int val in row)
                {
                    Console.Write($"{val},");
                }
            }
        }
    }
}

<実行結果>

40
30
10,20,30,40,50,60,70,80,90,10,20,30,
  • これは「配列の中にint[]を3個格納」しており、それぞれが4要素の配列を持っています。

7. 配列とオブジェクト指向

配列は非常に便利ですが、要素数を後から変更できないなどの制限があります。C#では可変長のコレクションとして List<T> などが用意されており、実務ではそちらを使う機会が多いでしょう。

例:配列で5名の生徒の成績を管理する

using System;

namespace Chap06
{
    public class Example09
    {
        public static void Main()
        {
            int[] scores = { 80, 75, 100, 90, 80 };
            string[] names = { "Tom", "John", "Mary", "Ken", "Jimmy" };

            for (int i = 0; i < scores.Length; i++)
            {
                Console.WriteLine($"{names[i]}'s score is {scores[i]}");
            }
        }
    }
}

<実行結果>

Tom's score is 80
John's score is 75
Mary's score is 100
Ken's score is 90
Jimmy's score is 80
  • 古典的にはこのように「別々の配列」で同じインデックスを共有していました。
  • しかしオブジェクト指向(クラス設計)が普及してからは、1人分のデータを1つのオブジェクトとしてまとめるやり方が主流となっています。

これで配列の基本的な使い方はバッチリです。次回は可変長コレクション(List<T> など)や、よりオブジェクト指向らしいデータ管理についても学んでいきましょう。


<まとめ:隣の人に正しく説明できたらチェックを付けましょう>

□ 配列は同じ型の複数の変数が並んだものと考えられる

□ 配列の添字(index)は0~(要素数-1)である

□ 拡張foreach文は配列の操作を簡潔に記述できます。

□ 参照型にはオブジェクト(配列含む)のアドレスが入っている

これらの基礎をしっかり押さえておくことで、C#プログラミングの理解が深まります。

まとめができたら、アウトプットとして演習問題にチャレンジしましょう。

最後までお読みいただきありがとうございます。