C#を用いたプログラミングにおいて、データの集合を扱う際に最も基本的かつ頻繁に利用されるのが「配列」です。

配列を操作する上で、その中にいくつの要素が含まれているのかを知ることは、ループ処理や境界チェックを行うために欠かせません。

しかし、C#には要素数を取得する方法としてLengthプロパティだけでなく、LINQのCount()メソッドや、多次元配列特有のGetLength()メソッドなどが存在し、初心者から中級者まで「どれをどの場面で使うべきか」迷うことがあります。

本記事では、C#における配列の要素数取得について、基本的な使い方から多次元配列・ジャグ配列での扱い、さらにはパフォーマンス面での注意点まで、プロフェッショナルな視点で詳しく解説します。

配列の要素数を取得する基本:Lengthプロパティ

C#の配列において、最も標準的かつ高速に要素数を取得する方法はLengthプロパティを使用することです。

Lengthプロパティの特徴

Lengthは、配列のすべての次元に含まれる要素の総数int型で返します。

これはSystem.Arrayクラスで定義されており、配列がインスタンス化された時点でそのサイズは固定されるため、非常に高速にアクセスできるという特徴があります。

C#
using System;

class Program
{
    static void Main()
    {
        // 要素数5の配列を宣言
        int[] numbers = { 10, 20, 30, 40, 50 };

        // Lengthプロパティで要素数を取得
        int count = numbers.Length;

        Console.WriteLine($"配列の要素数は {count} です。");
    }
}
実行結果
配列の要素数は 5 です。

巨大な配列を扱う場合のLongLength

通常の配列ではLengthで十分ですが、要素数が int.MaxValue(約21億)を超える可能性がある巨大な配列を扱う場合には、LongLengthプロパティを使用します。

これはlong(64ビット整数)型で要素数を返します。

通常のアプリケーション開発で遭遇することは稀ですが、データ分析や科学技術計算などで巨大なメモリを確保する際には覚えておくべき知識です。

LengthとLINQのCount()メソッドの違い

C#には、System.Linq名前空間をインポートすることで利用可能になるCount()という拡張メソッドも存在します。

これらは似ていますが、内部的な挙動やパフォーマンスには大きな違いがあります。

Count()メソッドとは

Count()は、IEnumerable<T>インターフェースを実装しているすべてのコレクションに対して使用できるメソッドです。

配列もこのインターフェースを実装しているため、Count()を呼び出すことが可能です。

使い分けの基準

  1. パフォーマンス: 配列に対してはLengthを使用するのが最適です。Lengthはプロパティへの直接アクセスであるのに対し、Count()はメソッド呼び出しのオーバーヘッドが発生します。
  2. 型の抽象化: メソッドの引数がIEnumerable<int>のように抽象化されている場合は、Count()を使用する必要があります。
  3. 条件付きカウント: 「特定の条件に一致する要素だけを数えたい」場合は、LINQのCount(x => x > 10)といった形式が非常に便利です。
C#
using System;
using System.Linq; // Count()を使用するために必要

class Program
{
    static void Main()
    {
        int[] numbers = { 5, 12, 8, 20, 15 };

        // プロパティによる取得(高速)
        int length = numbers.Length;

        // LINQメソッドによる取得
        int count = numbers.Count();

        // LINQによる条件付きカウント
        int conditionalCount = numbers.Count(n => n >= 10);

        Console.WriteLine($"Length: {length}");
        Console.WriteLine($"Count(): {count}");
        Console.WriteLine($"10以上の要素数: {conditionalCount}");
    }
}
実行結果
Length: 5
Count(): 5
10以上の要素数: 3

注意点: 最新の.NETでは、LINQのCount()内部で「対象が配列ならLengthを呼び出す」という最適化が行われていますが、それでも純粋なプロパティ参照よりはわずかにコストがかかります。

配列であることが確定している場面では、常にLengthを選択するのがベストプラクティスです。

多次元配列における要素数の取得

C#の多次元配列(矩形配列)において、Lengthプロパティを使用すると少し注意が必要です。

なぜなら、Length全次元の合計要素数を返してしまうからです。

GetLength(dimension)メソッド

特定の次元(行数や列数)の要素数を取得したい場合は、GetLength()メソッドを使用します。

引数には、取得したい次元のインデックス(0から始まる)を渡します。

  • 0番目の次元:行数(縦の長さ)
  • 1番目の次元:列数(横の長さ)
C#
using System;

class Program
{
    static void Main()
    {
        // 3行4列の2次元配列
        int[,] matrix = new int[3, 4];

        // 全要素数の取得
        Console.WriteLine($"全要素数 (Length): {matrix.Length}");

        // 行数の取得
        Console.WriteLine($"行数 (GetLength(0)): {matrix.GetLength(0)}");

        // 列数の取得
        Console.WriteLine($"列数 (GetLength(1)): {matrix.GetLength(1)}");
        
        // 次元数の取得
        Console.WriteLine($"次元数 (Rank): {matrix.Rank}");
    }
}
実行結果
全要素数 (Length): 12
行数 (GetLength(0)): 3
列数 (GetLength(1)): 4
次元数 (Rank): 2

多次元配列をループで処理する場合、外側のループでGetLength(0)、内側のループでGetLength(1)を使用するのが定石です。

ジャグ配列(配列の配列)における要素数の取得

ジャグ配列(Jagged Array)は「配列を要素として持つ配列」であり、多次元配列とは構造が異なります。

そのため、要素数の取得方法も異なります。

親配列と子配列のLength

ジャグ配列の場合、親となる配列のLength「格納されている配列の数」を表します。

それぞれの内部配列の要素数を知るには、個別の要素にアクセスした上でLengthを参照する必要があります。

C#
using System;

class Program
{
    static void Main()
    {
        // ジャグ配列の宣言
        int[][] jaggedArray = new int[3][];
        jaggedArray[0] = new int[] { 1, 2 };
        jaggedArray[1] = new int[] { 3, 4, 5, 6 };
        jaggedArray[2] = new int[] { 7 };

        // 親配列の要素数(内部配列がいくつあるか)
        Console.WriteLine($"親配列の長さ: {jaggedArray.Length}");

        // 各内部配列の要素数
        for (int i = 0; i < jaggedArray.Length; i++)
        {
            Console.WriteLine($"インデックス {i} の配列の長さ: {jaggedArray[i].Length}");
        }
    }
}
実行結果
親配列の長さ: 3
インデックス 0 の配列の長さ: 2
インデックス 1 の配列の長さ: 4
インデックス 2 の配列の長さ: 1

ジャグ配列では、GetLength()を使用することはできません(コンパイルエラーにはなりませんが、期待した多次元的な動作はしません)。

常に各階層でLengthを確認する形になります。

要素数取得時の注意点とTips

実務で配列の要素数を扱う際には、単に取得するだけでなく、実行時エラーを防ぐための考慮が必要です。

nullチェックと空の配列

配列変数がnullである場合、Lengthを参照しようとするとNullReferenceExceptionが発生します。

これを防ぐために、C#の「null条件演算子(?.)」や「null合体演算子(??)」を活用するのがモダンな書き方です。

C#
int[]? numbers = null;

// numbersがnullなら要素数0として扱う
int count = numbers?.Length ?? 0;
Console.WriteLine($"要素数: {count}"); // 出力: 要素数: 0

コレクション(List<T>)との混同に注意

C#では配列の他にもList<T>が多用されます。

配列はLengthですが、List<T>はCountプロパティを使用します。

  • 配列:array.Length
  • リスト:list.Count

開発環境(IDE)のインテリセンスで候補が出るため間違えることは少ないですが、静的解析ツールなどで指摘されるポイントの一つです。

パフォーマンスへの配慮

ループの条件式でLengthを記述すること(例:for (int i = 0; i < arr.Length; i++))は、C#において非常に高度に最適化されています。

JIT(Just-In-Time)コンパイラは、このパターンを認識すると「配列の境界チェック(Range Check)」を省略する最適化を行うことがあります。

そのため、あえてローカル変数に要素数をキャッシュするよりも、そのままLengthを使う方が安全かつ高速である場合が多いです。

まとめ

C#で配列の要素数を取得する方法について、状況に応じた使い分けを整理します。

基本(1次元配列)

1次元配列では主に Length プロパティを使用します。

読み取り専用で、配列の全要素数を高速に取得できます。

多次元配列

配列の全要素数は Length で取得し、特定の次元(行や列)のサイズは GetLength(index) を使用します。

ジャグ配列

各階層ごとに Length を使用して長さを取得します。

例: array[i].Length

階層ごとに長さが異なる点に注意してください。

LINQ(Countメソッド)

条件で絞り込んだ要素数を取得する場合は Count(LINQ)が適しています。

単純に全要素数を得るだけなら Length の使用が推奨されます(パフォーマンス上有利)。

安全性

null の可能性がある場合は例外を避けるために ?.Length ?? 0 のように null 条件演算子と null 合体演算子を組み合わせて記述しましょう。

配列の要素数を正確に把握し、適切に操作することは、堅牢で効率的なプログラムを書くための第一歩です。

特に多次元配列とジャグ配列の違いや、LINQとのパフォーマンス差を理解しておくことで、より高度なC#プログラミングが可能になります。

日常的なコーディングにおいては、まず「Lengthで取れるか?」を考え、特殊な構造や条件が必要な場合にのみ他の手段を検討すると良いでしょう。