shuhelohelo’s blog

Xamarin.Forms多めです.

C#でジェネリックと型引数と型制約

ジェネリッククラスについて自分なりのまとめ。

List<T>

といった、任意の型を指定できるクラス。

型引数について

正確ではないけれど、型引数はジェネリッククラスの中でプレースホルダーのように使われるイメージ。

ジェネリッククラスを使う際に型引数に具体的な型を指定すると、クラス内の各型プレースホルダーにそれらの具体的なクラスが当てはめられる。

例えば、以下のようなジェネリッククラスを定義する。

        //ジェネリックメソッド
        //二つの引数を入れ替えるだけ
        public static (T a, T b) MySwap<T>(T x, T y) //Tが型のプレースホルダーみたいなもの
        {
            return (y, x);
        }

これを呼び出し側で MySwap<string>("Hello1", "Hello2")とする。型引数にはstringを指定。

上記のジェネリックメソッドは以下のようにTの部分にstringが展開される。

        public static (string a, string b) MySwap<string>(string x, string y)
        {
            return (y, x);
        }

型引数は複数指定可能

<>には複数の型を指定できる。

        public static (T2 a, T1 b) MySwap<T1, T2>(T1 x, T2 y)
        {
            return (y, x);
        }

型制約

型制約は、指定可能な型引数を制限するための仕組み。

インスタンス化可能であることとか、特定のインターフェースを実装していることとか、whereを使って規定できる。

例えばT1インスタンス化できるクラスでなければならないという制約をつけたい場合は、

        public static (T2 a, T1 b) MySwap<T1, T2>(T1 x, T2 y) 
            where T1:new()
        {
            return (y, x);
        }

T2IEnumerable<string>を実装していなければならないのであれば、

        public static (T2 a, T1 b) MySwap<T1, T2>(T1 x, T2 y) 
            where T1:new()
            where T2:IEnumerable<string>
        {
            return (y, x);
        }

というように制約をつける。