我最近将一个项目从.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);
}
};
Run Code Online (Sandbox Code Playgroud)
在.NET 3.5中曾经Dequeue()
第一次调用它会触发静态初始化,它会运行静态构造函数.一旦我转移到.NET 4.0,从未调用静态构造函数.
我知道.NET 4.0中的静态初始化已经发生了变化,但根据我读到的所有内容,它应该可以正常工作.
在.NET中,只能在第一次访问字段时调用类型初始值设定项.这由[BeforeFieldInit]
属性控制.
我提交了一个错误报告,该报告仅供Beta测试人员使用,尽管标记为"公开".
以下是Microsoft的解释,您可能会发现它有用:
对于C++,这是预期的行为.我们用class标记我们的类
BeforeFieldInit
,因此CLR执行的初始化是正确的.我们没有在C++/CLI中提供一种方法来改变这种行为.如果需要运行类构造函数,则可以System.Runtime.CompilerServices.RuntimeHelpers::RunClassConstructor
显式调用.
由于我们在这里调用标准,分区I,8.9.5中的行说明了这一点:
如果标记为BeforeFieldInit,则类型的初始化方法在首次访问为该类型定义的任何静态字段时或之前执行.
该部分实际上详细介绍了语言实现如何选择阻止您描述的行为.C++/CLI选择不这样做,而是允许程序员在他们希望的情况下这样做.
基本上,由于下面的代码绝对没有静态字段,因此简单地不调用静态类构造函数就完全正确.