今回はC#のジェネリック<T>について解説します。
- ジェネリック<T>の役割を知りたい
- ジェネリック<T>の使い方を知りたい
- ジェネリックを使った関数やクラスの例を参考にしたい
ジェネリック<T>って何?
ジェネリックとは、クラス内の関数が同じで型だけ異なるものを共通化できるというものです。
C#を使っていると次のようなコードに出くわすことがあると思います。
public クラス名<T>
T
はジェネリッククラスと呼ばれています。
T
に対して任意に型を指定することができるようになるので、同じ関数を繰り返し書かなくてもいいメリットがあります。
ジェネリックメソッドを作ってみる
実際にジェネリックでメソッド(関数)を作成していきましょう。
ジェネリックメソッドを使わない場合
まずは、通常のメソッドを用いてx
とy
の掛け算の結果をint
とfloat
返す関数を作っていきます。
サンプルコード
/// <summary>
/// xとyの最大値を返す
/// </summary>
/// <param name="x">int型</param>
/// <param name="y">int型</param>
/// <returns>int型で結果を返す</returns>
static int Max(int x, int y)
{
return x > y ? x : y;
}
/// <summary>
/// xとyの最大値を返す
/// </summary>
/// <param name="x">float型</param>
/// <param name="y">float型</param>
/// <returns>float型で結果を返す</returns>
static float Max(float x, float y)
{
return x > y ? x : y;
}
ジェネリックメソッドを使う場合
ジェネリックメソッドは次のように作成します。
戻り値の型 メソッド名<型引数>()
{
}
先ほどのコードにジェネリックメソッドを適用するとこうなります。
/// <summary>
/// xとyの最大値を返す
/// </summary>
/// <typeparam name="T">ジェネリック</typeparam>
/// <param name="x">ジェネリック</param>
/// <param name="y">ジェネリック</param>
/// <returns></returns>
static T Max<T>(T x, T y) where T : IComparable
{
return x.CompareTo(y) > 0 ? x : y;
}
メソッド名の後ろに< >
で囲うことで、型をパラメータとして割り当てることができます。
制限事項として、C#でジェネリックを使うと比較演算子が使えなくなり、CompareTo
を使う必要が出てきます。
ジェネリックメソッドの呼び出し方
作成したジェネリックメソッドは以下のように呼び出します。
ジェネリックメソッドの呼び出し方
int a = Max<int>(5, 10); // int 版の Max を明示的に呼び出し
int b = Max(5, 10); // int 版の Max が自動的に生成される
double c = Max(5.0, 10.0); // double 版の Max が自動的に生成される
string d = Max("abc", "cat"); // string 版の Max (辞書式順序で比較)
Console.WriteLine("a:{0} type:{1}", a, a.GetType());
Console.WriteLine("b:{0} type:{1}", b, b.GetType());
Console.WriteLine("c:{0} type:{1}", c, c.GetType());
Console.WriteLine("d:{0} type:{1}", d, d.GetType());
実行結果
a:10 type:System.Int32
b:10 type:System.Int32
c:10 type:System.Double
d:cba type:System.String
ジェネリッククラスを作ってみる
関数と同じく、クラスにおいてもジェネリックを使うことができます。
ジェネリッククラスを使わない場合
まずは、通常のクラスを書いていきます。
GenericSample
というクラスの中に値をそのまま帰すAns1
、Ans2
という関数を用意してやります。
サンプルコード
public class GenericSample
{
/// <summary>
/// 値をそのまま返す
/// </summary>
/// <param name="num1">int型</param>
/// <returns></returns>
public int Ans1(int num1)
{
return num1;
}
/// <summary>
/// 値をそのまま返す
/// </summary>
/// <param name="num2">double型</param>
public double Ans2(double num2)
{
return num2;
}
}
ジェネリッククラスを使ったサンプルコード
ジェネリッククラスは次のように作成します。
class クラス名<>
{
}
先ほどのコードをジェネリッククラスに変換するとこんな感じになります。
サンプルコード
public class GenericSample<T>
{
/// <summary>
/// 値をそのまま返す
/// </summary>
/// <param name="num">ジェネリック</param>
/// <returns></returns>
public T Ans(T num)
{
return num;
}
}
ジェネリッククラスの呼び出し方
ジェネリッククラスを呼び出すためにはクラスのインスタンス生成時に型指定します。
具体的にはGenericSmaple<T>
のT
に対して、型指定して上げる必要があります。
ジェネリッククラスの呼び出し方
GenericSample<int> intGeneric = new GenericSample<int>();
GenericSample<double> floatGeneric = new GenericSample<double>();
var e = intGeneric.Ans(100);
var f = floatGeneric.Ans(1.23);
Console.WriteLine("a:{0} type:{1}", e, e.GetType());
Console.WriteLine("f:{0} type:{1}", f, f.GetType());
実行結果
a:100 type:System.Int32
f:1.23 type:System.Double
コメント