Переменная статического члена не инициализируется в выпуске - ошибка компилятора / clr? - PullRequest
6 голосов
/ 27 августа 2010

Ожидаемый вывод и вывод я получаю в режиме отладки и в режиме выпуска под VS2010, .NET 4.0:

bar construct
main

Вывод в режиме выпуска не под отладчиком VS2010 и под WinDbg:

main

Программа не демонстрирует такое поведение на VS2005, .NET 2.0

using System;

namespace static_init
{
    public class bar
    {
        public bar()
        {
            Console.WriteLine("bar construct");
        }
    }

    class Program
    {
        public static bar blah = new bar();

        static void Main(string[] args)
        {
            Console.WriteLine("main");
            Console.ReadLine();
        }
    }
}

Вероятно, связано: Статический конструктор может запускаться после нестатического конструктора. Это ошибка компилятора?

Обновление

В моем фактическом конструкторе кода bar() инициализирует некоторый код взаимодействия с C ++ (неуправляемый). Это должно произойти раньше, чем что-либо еще в этой библиотеке - есть ли способ убедиться, что без добавления в библиотеку функции init(), которая затрагивает всю статику (с побочными эффектами, на которые нет внешних ссылок) в библиотеке?

Примечание для будущих поисковиков: я использую SWIG, и это предположение, которое они сделали в своем коде генерации оболочки. SWIGStringHelper текущий нарушитель, хотя может быть и больше.

Заключение

Обновление SWIG до версии 2.0; в него добавляется статический конструктор, необходимый для более новой версии .NET.

Ответы [ 2 ]

10 голосов
/ 27 августа 2010

Вероятно, это оптимизируется, потому что вы его не используете.

Это также не ошибка компилятора, это в спецификации языка.

17.4.5.1 Инициализация статического поля

Статические инициализаторы переменных поля объявления класса соответствуют последовательность назначений, которые выполняется в текстовом порядке, в котором они появляются в объявлении класса. Если статический конструктор (§17.11) существует в классе, выполнение происходит инициализация статического поля непосредственно перед выполнением этого статический конструктор В противном случае инициализаторы статического поля выполняются во время, зависящее от реализации до первого использования статического поле этого класса

Поскольку вы никогда не используете статическое поле класса Program, не гарантируется, что статический инициализатор будет работать (хотя это может быть ... «зависящее от реализации время» выше)

Обновление
Вы можете достичь того, чего хотите, сделав в Программе статический конструктор.

static Program (){} или, возможно, путем доступа к другой (возможно, фиктивной) статической переменной

7 голосов
/ 27 августа 2010

Обратите внимание, что в .NET 4.0 произошли некоторые изменения, касающиеся статической инициализации. Джон Скит написал в блоге несколько примеров:

Изменения инициализации типа в .NET 4.0

Если вы хотите точной инициализации, вы должны использовать статический конструктор (который может быть пустым).

using System;

namespace static_init
{
    public class bar
    {
        public bar()
        {
            Console.WriteLine("bar construct");
        }
    }

    class Program
    {
        public static bar blah = new bar();

        // This static constructor will make sure that the type Program 
        // is initialized before it is first used.
        //
        static Program()
        { }

        static void Main(string[] args)
        {
            Console.WriteLine("main");
            Console.ReadLine();
        }
    }
}
...