Управляемый статический конструктор C ++ не вызывается в .net4 - PullRequest
2 голосов
/ 24 января 2012

Я недавно переместил проект, над которым работаю, из .NET 3.5 в .NET 4. Я использую C #, Managed C ++ и Unmanaged C ++.

В одном из моих Managed C ++ (взаимодействие) У меня статический конструктор:

public ref class StaticPool : public BaseStaticPools
{
public:
    static StaticPool()
    {                       
        InitializePools();
    }

    static Poolable^ Dequeue()
    {
        return (Poolable^)Dequeue(Poolable::typeid);
    }

private:
    static void InitializePools()
    {                       
        BaseStaticPools::CreatePool(Poolable::typeid);                      
    }
};

В .NET 3.5 после первого вызова Dequeue() будет запускаться статическая инициализация, которая запускает статический конструктор.После того, как я перешел на .NET 4.0, статический конструктор так и не был вызван.

Я знаю, что в статической инициализации в .NET 4.0 произошли изменения, но, как я прочитал, все должно работать нормально.

Ответы [ 2 ]

5 голосов
/ 24 января 2012

В .NET инициализаторы типов могут вызываться только при первом обращении к полю. Это контролируется атрибутом [BeforeFieldInit].

Я отправил отчет об ошибке, который доступен только для бета-тестеров, несмотря на то, что он помечен как «Публичный».

Вот объяснение от Microsoft, которое может оказаться полезным:

Для C ++ это предполагаемое поведение. Мы помечаем наши классы BeforeFieldInit, и поэтому инициализация, выполняемая CLR, правильная. Мы не предлагаем в C ++ / CLI способ изменить это поведение. Если вам требуется для запуска конструктор класса, вы можете явно вызвать System.Runtime.CompilerServices.RuntimeHelpers::RunClassConstructor.


Поскольку здесь мы ссылаемся на стандарт, строка из Раздела I, 8.9.5, гласит:

Если помечен BeforeFieldInit, тогда метод инициализатора типа выполняется во время или за некоторое время до первого доступа к любому статическому полю , определенному для этого типа.

В этом разделе подробно рассказывается о том, как языковая реализация может выбрать предотвращение поведения, которое вы описываете. C ++ / CLI решает не делать этого, скорее, они позволяют программисту делать это, если хотят.

По сути, , так как в приведенном ниже коде нет абсолютно никаких статических полей, JIT совершенно корректен, просто не вызывая конструкторы статических классов .

3 голосов
/ 13 апреля 2012

Джон Скит писал на эту тему:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...