код:
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 нужно просто вызывать один раз, я предпочитаю подход отражения, потому что в некоторых случаях ограничение new () просто не является выбором - как будто вы не должны предоставлять ctor без параметров пользователю.
После проведения дальнейшего эксперимента я обнаружил, что .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