.net4中未调用托管C++静态构造函数

本文关键字:C++ 静态 构造函数 调用 net4 | 更新日期: 2023-09-27 18:21:20

我最近将正在进行的一个项目从.NET 3.5迁移到了.NET 4。我使用的是C#、托管C++和非托管C++。

在我的一个托管C++(interop)中,我有一个静态构造函数:

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);                      
    }
};

在.NET3.5中,一旦第一次调用Dequeue(),它将触发静态初始化,该初始化将运行静态构造函数。一旦我转到.NET 4.0,就再也没有调用过静态构造函数。

我知道.NET 4.0中的静态初始化发生了变化,但据我所知,它应该可以正常工作。

.net4中未调用托管C++静态构造函数

在.NET中,类型初始值设定项只能在第一次访问字段时调用。这是由[BeforeFieldInit]属性控制的。

我提交了一份错误报告,尽管被标记为";公开";。

以下是微软的解释,你可能会觉得很有帮助:

对于C++,这是预期的行为。我们用BeforeFieldInit标记类,因此CLR正在执行的初始化是正确的。我们在C++/CLI中没有提供更改此行为的方法。如果需要运行类构造函数,则可以显式调用System.Runtime.CompilerServices.RuntimeHelpers::RunClassConstructor


由于我们在这里调用标准,分区I中的行8.9.5是这样写的:

如果标记为BeforeFieldInit,则类型的初始值设定项方法将在首次访问为该类型定义的任何静态字段时或之前执行。

该部分实际上详细介绍了语言实现如何选择阻止您所描述的行为。C++/CLI选择不这样做,而是允许程序员根据自己的意愿这样做。

基本上,由于下面的代码绝对没有静态字段,JIT完全正确地不调用静态类构造函数

Jon Skeet在这个主题上写道:

在.NET 4.0 中键入初始化更改