ネコのために鐘は鳴る

寺院に住み着くパソコ〇好き

(C#) ジェネリック型制約違いのオーバーロード

小ネタです。

C#ジェネリックメソッドには型制約をつけることができます。 この時、C# ではシグネチャ (メソッド名、引数、戻り値など) が同じでジェネリック型制約のみが異なるメソッドはオーバーロードとして書くことができません。

public static void Foo<T>(this T value) where T : class
{
}

// コンパイルエラー!!
public static void Foo<T>(this T value) where T : struct, Enum
{
}

C# の文法的にどうしようもないので、以下のコードで妥協しました。

public static void Foo<T>(this T value, ClassMarker _ = default)
    where T : class
{
}

public static void Foo<T>(this T value, EnumMarker _ = default)
    where T : struct, Enum
{
}

public struct ClassMarker { }
public struct EnumMarker { }

マーカー用の型を作って、メソッドの二番目の引数に追加してデフォルト引数を追加しておきます。

こうするとシグネチャが異なるのでオーバーロードでき、なおかつメソッド使用者側は二番目の引数を省略できるので2つとも同じ書き方ができます。

ライブラリとして public に露出するメソッドとしてはよくないかもしれませんが、使いどころによっては便利に書けるかもしれないです。

public enum Animal 
{
    Dog, Cat,
}

// クラス引数ののオーバーロード
"hello".Foo();
// enum 引数のオーバーロード
Animal.Dog.Foo();