ジェネリック メソッド (C# プログラミング ガイド)
ジェネリック メソッドは、型パラメーターと共に次のように宣言されるメソッドです。
static void Swap<T>(ref T lhs, ref T rhs)
{
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
次のコード例は、型引数として int を使用してメソッドを呼び出す方法を示しています。
public static void TestSwap()
{
int a = 1;
int b = 2;
Swap<int>(ref a, ref b);
System.Console.WriteLine(a + " " + b);
}
型引数は省略することもできます。省略された型引数は、コンパイラが推論します。次に示す Swap の呼び出しは、上の呼び出しと同じです。
Swap(ref a, ref b);
静的メソッドにもインスタンス メソッドにも同じ型の推定規則が適用されます。コンパイラは、渡されたメソッド引数に基づいて型パラメーターを推論できます。制約や戻り値のみから型パラメーターを推論することはできません。そのため型の推定は、パラメーターを持たないメソッドでは無効です。型の推定は、コンパイル時にコンパイラが、オーバーロードされたメソッド シグネチャを解決しようとする前に行われます。コンパイラは、同じ名前を持つすべてのジェネリック メソッドに型の推定ロジックを適用します。オーバーロード解決ステップで、コンパイラは、型の推定が成功したジェネリック メソッドのみを取り込みます。
ジェネリック クラス内の非ジェネリック メソッドは、クラスレベルの型パラメーターに次のようにアクセスできます。
class SampleClass<T>
{
void Swap(ref T lhs, ref T rhs) { }
}
格納する側のクラスと同じ型パラメーターを受け取るジェネリック メソッドを定義した場合、コンパイラは警告 CS0693 を生成します。これは、メソッドのスコープ内で、内側の T に指定された引数が、外側の T に指定された引数を隠すためです。クラスをインスタンス化したときに指定した以外の型引数を使ってジェネリック クラス メソッドを柔軟に呼び出す必要がある場合は、次の例の GenericList2<T> に示されているように、メソッドの型パラメーターに別の識別子を指定することを検討してください。
class GenericList<T>
{
// CS0693
void SampleMethod<T>() { }
}
class GenericList2<T>
{
//No warning
void SampleMethod<U>() { }
}
メソッドの型パラメーターでより特殊な演算を実現するには、制約を使用します。次に示す SwapIfGreater<T> という Swap<T> のバージョンは、IComparable<T> を実装する型引数でのみ使用できます。
void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
{
T temp;
if (lhs.CompareTo(rhs) > 0)
{
temp = lhs;
lhs = rhs;
rhs = temp;
}
}
ジェネリック メソッドは、いくつかの型パラメーターでオーバーロードできます。たとえば、次のメソッドは、同じクラスにすべて置くことができます。
void DoWork() { }
void DoWork<T>() { }
void DoWork<T, U>() { }
C# 言語仕様
詳細については、「C# 言語仕様」を参照してください。