Статический конструктор С# не вызывается из производного класса

class Bus<T>
{
    static Bus()
    {
        foreach(FieldInfo fi in typeof(T).GetFields())
        {
            if(fi.FieldType == typeof(Argument))
            {
                fi.SetValue(typeof(T), new Argument("busyname", "busyvalue"));
            }
        }
    }
}
class Buss : Bus<Buss>
{
    public static Argument field;
}

Любые идеи, как заставить это работать, чтобы ссылка на статическое поле в Buss запускала статический конструктор в Bus?


person Trevor    schedule 17.06.2011    source источник
comment
почему статические конструкторы? Статический конструктор используется для инициализации любых статических данных или для выполнения определенного действия, которое необходимо выполнить только один раз.   -  person adt    schedule 17.06.2011
comment
'field' является статическими данными, и их нужно инициализировать только один раз, следовательно, это статические конструкторы.   -  person Trevor    schedule 18.06.2011


Ответы (3)


Тот факт, что это важно для вас, вероятно, означает, что вы неправильно используете статические конструкторы.

Имея это в виду, вы можете создать статический конструктор в Buss, который вручную вызывает статический конструктор в Bus. Обратите внимание, что статический конструктор невозможно запустить более одного раза.

person recursive    schedule 17.06.2011
comment
статический конструктор нельзя вызвать напрямую. - person adt; 17.06.2011
comment
Я понимаю, что под «неправильным» вы, вероятно, подразумеваете, что мой ООП отключен. Однако я чувствую, что возможность наследовать статические члены (включая статические конструкторы) на самом деле была бы более объектно-ориентированной. - person Trevor; 18.06.2011
comment
@adt: Просто обратитесь к любому статическому полю или методу, и он будет вызван неявно. - person recursive; 18.06.2011
comment
Вы можете напрямую вызвать статический конструктор? - person adt; 19.06.2011
comment
@adt: Не явно, но вызов может быть выполнен, как я уже упоминал. - person recursive; 20.06.2011

Статический конструктор универсального типа вызывается ровно один раз для каждого Type при ссылке на этот тип.

Вызов Buss x = new Buss() вызовет статический конструктор Bus<Buss>.

Вызов Bus<Buss> x = new Bus<Buss>() также вызовет статический конструктор Bus<Buss>, но он сделает это для аргумента типа Buss, установив Buss.field.

Если вы создадите class Bugs : Bus<Buss>, он никогда не установит Bugs.field, так как он сначала разрешит аргумент типа Buss, который вызывает статический конструктор своего базового класса Bus<Buss>, устанавливая Buss.field. Когда он попытается вызвать статический конструктор базового класса Bugs, он подумает, что уже вызвал статический конструктор Bus<Buss>, и пропустит его.

По сути, если я копирую и вставляю ваш код, создаю фиктивный класс Argument и создаю новый экземпляр Buss, вызывается статический конструктор и Buss.field устанавливается на экземпляр Argument, но я узнаю здесь какое-то странное поведение, в котором я должен был бы посоветовать не использовать отражение от статического метода для достижения статики подклассов.

Приведенный вами пример работает только потому, что Buss является аргументом типа для себя.

person C.Evenhuis    schedule 17.06.2011

MSDN сообщает, что "Статические конструкторы не передается по наследству». Я предполагаю, что это похоже на статические поля, которые также не наследуются.

person marto    schedule 17.06.2011
comment
статические поля, которые не наследуются: у меня в коде (упрощенном) class T1{ public static string s1="s1"; } class T2: T1 { void f(){ Console.WriteLine(s1); }}. Это не считается наследством? Можно с полным основанием ожидать, что статический конструктор базового класса будет выполнен до того, как будет выполнен статический конструктор одного из его подклассов, поскольку он также может выполнять статическую инициализацию, необходимую производному классу. - person Peter - Reinstate Monica; 20.01.2015