次の方法で共有


ジェネリック メソッド (C# プログラミング ガイド)

ジェネリック メソッドは、次のように型パラメーターで宣言されるメソッドです。

static void Swap<T>(ref T lhs, ref T rhs)
{
    T temp;
    temp = lhs;
    lhs = rhs;
    rhs = temp;
}

メソッドの呼び出し方法の 1 つを示しているのが次のコード サンプルです。型引数に 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>() { }

メソッドの戻り値の型として型パラメーターを使用することもできます。 次のコード例は、T 型の配列を返すメソッドを示しています。

T[] Swap<T>(T a, T b)
{
    return [b, a];
}

C# 言語仕様

詳細については、「C# 言語の仕様」を参照してください。

関連項目