ジェネリックはC#における機能の一つで「定義は一つだけど、中身が同じものを共通化できる」という特性をもっています。この記事ではジェネリックを使って「クラス」を共通化する方法を解説します。ジェネリックに関する記事は以下からチェックできます。
ジェネリッククラスの定義
当ブログの「【C#】ジェネリックメソッドで処理を共通化する方法」でも解説していますが、ジェネリックのクラスはメソッドにも似ています。まずはジェネリッククラスを作成する定義を確認していきましょう。
アクセス修飾子 class クラス名<型引数>
{
//クラスの記述
}
ジェネリッククラスのサンプル
以下、ジェネリッククラスを使用したサンプルを紹介します。基本的にはジェネリックメソッドと同じであることがわかるかと思います。
//App03
var c1 = new SampleClass<int>();
var ret1 = c1.Max(1, 10);
Console.WriteLine(ret1.ToString());
var c2 = new SampleClass<double>();
var ret2 = c2.Max(0.8, 0.9);
Console.WriteLine(ret2.ToString());
Console.ReadLine();
public class SampleClass where T : IComparable
{
public T Max(T a, T b)
{
return a.CompareTo(b) >= 0 ? a : b;
}
}
サンプルクラスとして定義しているのは以下の部分だけです。
public class SampleClass where T : IComparable
{
public T Max(T a, T b)
{
return a.CompareTo(b) >= 0 ? a : b;
}
}
ジェネリッククラスではメソッドと同じように、クラスの後に型引数を記載します。サンプルでは「<int>」「<double>」の部分になります。また型引数に対して制約を加える場合に where T : ~ の部分もジェネリックメソッドと一緒ですね。
ジェネリックメソッドで定義したものと同様に「IComparable を実装している型のみを対象とする」という制約を加えています。このように制約を加えることで T に対する処理の前提を付け加えることができます。ジェネリッククラスをインスタンス化する場合は、以下のようにすることでオブジェクトを生成できます。
var c1 = new SampleClass<int>();
var c2 = new SampleClass<double>();
クラスをインスタンス化する際に型を指定して、クラスをインスタンス化することができます。「SampleClassにおける T の型引数は int(double, float) として扱います」を宣言していることになります。これは C#の List<int> / List<string> と同様の宣言方法でも一緒です。
ジェネリックでクラスを共通化しよう
ジェネリックについては「型制約」「メソッド」「クラス」でおおむね内容はカバーされていると思います。ジェネリックのクラスを使うことで「同じ処理を持つクラスだけど、型毎にクラスを作るのは大変」というときに重宝します。
ジェネリックを使うことで、ソースコードの記述量を減らすことができるので、使える部分で活用していけるとよいと思います。ただしジェネリックを使うときは「【C#】ジェネリックでの「型制約」は重要であるという話」でも解説しているとおり、型制約はしっかりとしておいたほうが無難です。