Почему не все статические конструкторы вызываются в C # (то есть те из родительских классов)? - PullRequest
6 голосов
/ 28 июня 2011

У меня есть три класса, Base, Derived и Final. Derived происходит от Base и Final происходит от Derived. Все три класса имеют статический конструктор. Класс Derived как открытый статический метод с именем Setup. Когда я вызываю Final.Setup, я ожидаю, что все три статических конструктора будут выполнены, но только один из Derived будет запущен.

Вот пример исходного кода:

    abstract class Base
    {
        static Base()
        {
            System.Console.WriteLine ("Base");
        }
    }

    abstract class Derived : Base
    {
        static Derived()
        {
            System.Console.WriteLine ("Derived");
        }

        public static void Setup()
        {
            System.Console.WriteLine ("Setup");
        }
    }

    sealed class Final : Derived
    {
        static Final()
        {
            System.Console.WriteLine ("Final");
        }
    }

Это имеет для меня лишь частичный смысл. Я понимаю, что вызов Final.Setup() на самом деле является просто псевдонимом для Derived.Setup(), поэтому пропуск статического конструктора в Final кажется достаточно справедливым. Однако почему не вызывается статический конструктор Base?

Я могу это исправить, вызвав статический метод без операции Base или получив доступ к некоторому фиктивному статическому методу Base. Но мне было интересно: в чем причина этого, по-видимому, странного поведения?

Ответы [ 3 ]

5 голосов
/ 28 июня 2011

Статический конструктор вызывается, когда (согласно TCPL ):

  • Создается экземпляр типа класса.
  • Любой из статических членовссылки на тип класса.

В качестве примера рассмотрим класс со статическим методом Main, в котором начинается выполнение: если у вас есть статический конструктор, он будет вызываться до Метод Main вызывается.

Обратите внимание, что даже перед выполнением статического конструктора любые статические поля инициализируются в их значение по умолчанию, а затем для этих полей выполняются инициализаторы статического поля.Только тогда выполняется статический конструктор (cctor).


Чтобы ответить на ваш вопрос более прямо: статические конструкторы не наследуются и их нельзя вызывать напрямую, следовательно, ваш Base cctor не будетвызывается в вашем сценарии, если вы не передаете абстрактному классу Base статический метод и сначала вызываете его, т. е. как в Base.Initialize(), как вы уже предложили.

По поводу простого мышления C # (в Java это отличается): статические методы не наследуются, поэтому статические конструкторы не должны наследоваться, так как это может вызвать нежелательные побочные эффекты (cctor вызывается, когда ничего не ссылаетсяэтот класс).

1 голос
/ 28 июня 2011

Статические методы принадлежат классу и не имеют наследования.Тот факт, что вы можете вызывать Final.Setup, является просто синтаксическим сахаром для вызова Derived.Setup, поэтому на статический член Final не ссылались - поэтому статический конструктор не вызывается.То же самое для базового класса - наследование статических членов отсутствует, поэтому базовый класс здесь никак не задействован.

0 голосов
/ 28 июня 2011

Правила C # предписывают, чтобы статические конструкторы вызывались до создания первого экземпляра класса или касания любого статического члена, поэтому, возможно, никогда, как в вашем случае.

...