C#で基底クラスの静的メソッドから、メソッドを実行している派生クラスの型を知りたかったのでジェネリックを使った

 前回に基底クラスの静的メソッドから、メソッドを実行している派生クラスの型を得るのに失敗した。今回はそれをジェネリックを使って解決する。

 ジェネリックってなに?というのはもうだいぶ前からあるものなので、ちゃんとした説明は他ページを参照。
http://ufcpp.net/study/csharp/sp2_generics.html
”さまざまな型に対応するために、型をパラメータとして与えて、その型に対応したクラスや関数を生成するもの”
 ↑が参考にしたページに載っていたジェネリックの説明。例えば、この一例として「型をパラメータとして与えて、その型に対応した関数を生成する」ことを考える。ある一つの関数の定義として、パラメータで型を与える。この関数の定義にジェネリックを利用すれば、この関数の定義は一つなのに、関数からの返り値をパラメータで与える型に合わせて変えていくことができる。動的型付け言語をやってきた人なら違和感はないだろうが、静的型付け言語をやってきた人なら、お、となるところではないだろうか。その辺の例は参照先にあるのでここでは割愛。

 ジェネリックを利用して、基底クラスで定義された静的メソッドの中から、そのメソッドが実行される派生クラスの型を得る。「型をパラメータとして与えて、関数内でその型を利用する」ということをやる。なんで型が欲しいかってのは、リフレクションをやりたいからなの。

class Program

{
static void Main(string[] args)
{
Console.WriteLine(Class1.GetDerivedType<Class1>());
}
}

public class Class1 : BaseClass1
{
}

public abstract class BaseClass1
{
public static string GetDerivedType<T>() where T : BaseClass1
{
var t = typeof(T);
return t.Name;
}
}


 上記を実行すれば、"Class1"が出力される。これでClass1にもっといろいろ定義してあれば、リフレクションを使ってもろもろ読み出すことができる。でも個人的に読み出しの形をメソッドではなくプロパティにしたかったので書き換え。

class Program

{
static void Main(string[] args)
{
Console.WriteLine(Class2.DerivedType);
}
}

public class Class2 : BaseClass2<Class2>
{
}

public abstract class BaseClass2<T>
{
public static string DerivedType
{
get
{
var t = typeof(T);
return t.Name;
}
}
}

 これでもメソッドでやってたのと等価な結果となる。静的クラスで定義されたメンバから、派生クラスで実行時の型が使えるようになったので問題解決。

 あらためて派生クラスを見返してみると、変な形になってるんじゃないかと思った。けどもこれはデザインパターンの定石の一つとして、「奇妙に再帰したテンプレートパターン」という名前がついているようだ。
https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
More C++ Idioms/奇妙に再帰したテンプレートパターン(Curiously Recurring Template Pattern)
comment: 0