ジェネリックの利点 (C# プログラミング ガイド)

更新 : 2007 年 11 月

ジェネリックを使用することによって、汎用基本型 Object との値で型をキャストして一般化を行う、共通言語ランタイムや C# 言語の以前のバージョンの制限を解決できます。ジェネリック クラスを作成すると、コンパイル時にタイプ セーフなコレクションを作成できます。

ジェネリック以外のコレクション クラスを使用する際の制限は、.NET Framework クラス ライブラリの ArrayList コレクション クラスを使用する短いプログラムを作成してみるとわかります。ArrayList は、変更なしで参照型や値型を格納できるたいへん便利なコレクション クラスです。

// The .NET Framework 1.1 way to create a list:
System.Collections.ArrayList list1 = new System.Collections.ArrayList();
list1.Add(3);
list1.Add(105);

System.Collections.ArrayList list2 = new System.Collections.ArrayList();
list2.Add("It is raining in Redmond.");
list2.Add("It is snowing in the mountains.");

ただし、この利便性の一方でマイナス面もあります。ArrayList に追加される参照型や値型は暗黙的に Object にアップキャストされます。項目が値型の場合は、リストに追加するときにボックス化し、取得するときにボックス化解除する必要があります。キャスト操作もボックス化およびボックス化解除操作もパフォーマンスに影響します。ボックス化およびボックス化解除の影響は、大型のコレクションの反復処理が必要な場合に非常に大きくなります。

また、コンパイル時の型チェックがないという制限もあります。ArrayList はすべてを Object にキャストするため、コンパイル時にクライアント コードが次のような処理を行うのを防止できません。

System.Collections.ArrayList list = new System.Collections.ArrayList();
// Add an integer to the list.
list.Add(3);
// Add a string to the list. This will compile, but may cause an error later.
list.Add("It is raining in Redmond.");

int t = 0;
// This causes an InvalidCastException to be returned.
foreach (int x in list)
{
    t += x;
}

異種コレクションを作成することは有効であり、意図的に行うこともありますが、その場合、文字列と int を 1 つの ArrayList に組み合わせると、プログラミング エラーになる可能性があります。このエラーは、実行時まで検出されません。

C# 言語の Version 1.0 および 1.1 では、.NET Framework 基本クラス ライブラリのコレクション クラスにおける一般化されたコードの問題は、独自の型に固有のコレクションを記述することによってのみ回避できました。もちろん、このようなクラスは複数のデータ型で再利用できないため、一般化のメリットがなく、格納する型ごとにクラスを書き直す必要があります。

ArrayList や他の同じようなクラスで実際に必要なのは、クライアント コードで、使用する特定のデータ型をインスタンスごとに指定する方法です。このような方法があれば、T:System.Object にアップキャストする必要性がなくなり、またコンパイラが型チェックを実行することもできるようになります。言い換えれば、ArrayList には型パラメータが必要なのです。これを実現するのがジェネリックです。N:System.Collections.Generic 名前空間の List<T> ジェネリック コレクションでは、コレクションに項目を追加するという同じ操作が次のようになります。

// The .NET Framework 2.0 way to create a list
List<int> list1 = new List<int>();

// No boxing, no casting:
list1.Add(3);

// Compile-time error:
// list1.Add("It is raining in Redmond.");

クライアント コードでは、ArrayList と比較される List<T> と共に追加される構文は、宣言とインスタンス化での型引数だけです。このようにコーディングは若干複雑になりますが、それと引き換えに、ArrayList よりも安全であるだけでなく、特にリスト項目が値型のときには処理時間が大幅に短縮されるリストを作成できます。

参照

概念

C# プログラミング ガイド

参照

ジェネリックの概要 (C# プログラミング ガイド)

System.Collections.Generic

ボックス化とボックス化解除 (C# プログラミング ガイド)

その他の技術情報

コレクションのベスト プラクティス