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

时间:2012-01-24 15:01:14

标签: c# .net c++-cli

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

在我的一个托管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 个答案:

答案 0 :(得分:5)

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

我提交了一份错误报告,该报告仅供Beta测试人员使用,尽管被标记为“公开”。

以下是Microsoft的解释,您可能会对此有所帮助:

  

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


  

由于我们在这里调用标准,分区I,8.9.5中的行说明了这一点:

     

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

     

该部分实际上详细介绍了语言实现如何选择阻止您所描述的行为。 C ++ / CLI选择不这样做,而是允许程序员在他们希望的情况下这样做。

     

基本上,因为下面的代码绝对没有静态字段,所以JIT完全正确,只是不调用静态类构造函数

答案 1 :(得分:3)

Jon Skeet写了这个话题:

Type initialization changes in .NET 4.0