C#のGenericsのオーバーロードが便利だった話

C#の技術記事。コード内容はUnity寄り。

コルーチンをまとめたクラスを設計していて、

AddRoutine (Func<IEnumerator> routine)

みたいなコードを書いた。

これは、たとえば

IEnumerator RoutineA () { ... }

void Main ()
{
    var routines = CoroutineContainer();
    routines.AddRoutine(RoutineA);
}

みたいなのを書けるようにするためのコード。

で、この場合RoutineAが引数を持ってないからいいんだけど、

IEnumerator RoutineB (int arg) { ... }とか
IEnumerator RoutineC (string arg) { ... }とかの
引数ありのコルーチンって結構ある。

で、じゃあ

AddRoutine (Func<int,IEnumerator> routine, int arg)
AddRoutine (Func<string,IEnumerator> routine, string arg)
2つを定義しておけば、intとstringは対応できる。

でも、他の型でも対応したい。型指定しないで使えるようにしたいって思った。
そんなときのためにGenericsという仕組みがあったのだった。

AddRoutine<T> (Func<T,IEnumerator> routine, T arg)

こいつを定義しておけば、さっきの2つのオーバーロードは必要なくなる。
こいつを使ってRoutineBをAddRoutineしたいときは、
routines.AddRoutine<int>(RoutineB, x);みたいに書けばいい。

しかしGenericsの良さはとどまるところを知らなかった。
C#型推論の仕組みがあり、Genericsの指定も省略できる。
つまり、一つ上の例では、xがintなら、このように書ける。

routines.AddRoutine(RoutineB, x);

この型推論によってGenericsの型指定を省略できるのにいたく感動して記事にした。