コード:
class Base<T,U> where T:Base<T,U>,new() where U :class
{
protected static U _val = null;
internal static void ShowValue()
{
if(_val == null)new T(); //Without this line, it won't work as expected
Console.WriteLine (_val);
}
internal static void Virtual()
{
Console.WriteLine ("Base");
}
}
class Deriv :Base<Deriv,string>
{
static Deriv()
{
_val = "some string value";
}
internal static new void Virtual ()
{
Console.WriteLine ("Deriv");
}
}
public static void Main (string[] args)
{
Deriv.ShowValue();
Deriv.Virtual();
}
.NET のジェネリックのおかげで、ジェネリック基本クラスで定義されたジェネリック静的メソッドを再利用して、一連の特定のクラスを作成できます。継承ポリモーフィズムをある程度模倣できます。しかし、異なるバージョンの静的フィールドを初期化するには、静的コンストラクターを使用する必要があります。残念ながら、それらを直接呼び出すことはできないため、その呼び出しをトリガーする方法を見つけ出す必要があります。上記の例は方法を示しています。しかし、インスタンス化やリフレクションのアプローチは好きではありません。また、ジェネリック パラメーターの静的メソッドに制約を作成することもできません。それで、この種の仕事をする別の方法があれば、私は尋ねたいです!
よろしくお願いします!
~~~~~~~~~~~~~~~~
いくつかの結論(少し早いかもしれません):
この種の状況に対処するための回避策はないようです。サブクラスをインスタンス化するか、リフレクションを使用する必要があります。.cctors を一度だけ呼び出す必要があることを考えると、パラメーターなしの ctor をユーザーに公開しないように、 new() 制約を選択できない場合があるため、リフレクション アプローチを支持します。
さらに実験を行った後、.cctors は複数回呼び出される可能性がありますが、最初の呼び出しのみが静的フィールドの設定に影響することがわかりました。それは奇妙ですが、良い奇妙さです!
class MyClass
{
static int _val = 0;
static MyClass()
{
_val++;
Console.WriteLine (_val);
}
}
public static void Main (string[] args)
{
ConstructorInfo ci = typeof(MyClass).TypeInitializer;
ci.Invoke(new object[0]);
ci.Invoke(new object[0]);
ci.Invoke(new object[0]);
}
//result:
//1
//1
//1
//1