Статическая переменная-член не инициализируется в выпуске - ошибка компилятора / clr?

Ожидаемый вывод и вывод я получаю в режиме отладки, а в режиме выпуска под 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.

6
задан Community 23 May 2017 в 11:53
поделиться

2 ответа

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

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

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

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

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

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

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

11
ответ дан 8 December 2019 в 12:56
поделиться

Обратите внимание, что в .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();
        }
    }
}
7
ответ дан 8 December 2019 в 12:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: