trsing’s diary

勉強、読んだ本、仕事で調べたこととかのメモ。

EFFECTIVE C# 6.0/7.0 読書メモ 項目25

25 型引数がインスタンスのフィールドではない場合にはジェネリックメソッドとして定義すること

次の条件に該当しないのなら、ジェネリッククラスではなく非ジェネリッククラス内のジェネリックメソッドを定義するとよい。

ジェネリックメソッドのメリット

ユーザーとしては呼び出すのが楽(型の指定が必要ではない)。
作成者としてはアルゴリズムを更新する際の選択肢を増やすことができる(コンパイラが最適なメソッドを選択してくれる)。

ジェネリッククラスを定義

毎回型パラメータを指定する必要がある。
型によらずComparer.Default.Compare()が使用される。
実行時の型がIComparerを実装しているかを実行時に確認、適切なメソッドを呼び出すという手間がかかる

public static class Utils<T>
{
    public static T Max(T left, T right) =>
        Comparer<T>.Default.Compare(left, right) < 0 ? right : left;
    //略
}
double d1 = 4;
double d2 = 5;
double max = Utils<double>.Max(d1, d2);//型パラメータを指定

ジェネリッククラスにジェネリックメソッドを定義

型指定が不要。自動的に最適な型が呼ばれる。
ジェネリックバージョンより効率的。
後から型固有のメソッドを追加できる。

public class Utils
{
    public static T Max<T>(T left, T right) =>
        Comparer<T>.Default.Compare(left, right) < 0 ? right : left;
    public static double Max(double left, double right) =>//double型であればこっちが呼ばれる
        Math.Max(left, right);
    //public static double Max(int left, int right) =>//後からint型用のメソッドを追加できる
        Math.Max(left, right);
    //略
}
double d1 = 4;
double d2 = 5;
double max = Utils.Max(d1, d2);//型パラメータの指定不要