托管C ++静态构造函数不叫.NET4 [英] Managed C++ Static Constructor not called in .net4

查看:129
本文介绍了托管C ++静态构造函数不叫.NET4的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近提出一个项目,我的工作从.NET 3.5我使用C#,托管C ++和非托管C ++到.NET 4。

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

 公开引用类STATICPOOL:公共BaseStaticPools
{
上市:
    静态STATICPOOL()
    {
        InitializePools();
    }

    静态池化^出列()
    {
        返回(池化^)出列(池化:: typeid的);
    }

私人:
    静态无效InitializePools()
    {
        BaseStaticPools :: CreatePool(池化:: typeid的);
    }
};
 

在.NET 3.5中,一旦出列()已被要求在第一时间将触发静态初始化,它运行的静态构造函数。有一次,我搬到了.NET 4.0,静态构造函数永远不会被调用。

我知道,在静态初始化在.NET 4.0中已经改变,但根据我所读它应该很好地工作。

解决方案

在.NET中,类初始化可能只能被称为第一次现场访问。这是由 [BeforeFieldInit] 属性控制。

我提交了错误报告,该报告仅提供给测试者,尽管被标记为公开。

下面是来自微软,你可以找到有用的解释:

  

对于C ++,这是预期的行为。我们纪念我们的课程与 BeforeFieldInit ,所以CLR正在执行的初始化是正确的。我们不提供一种方法在C ++ / CLI来改变这种行为。如果您需要在类的构造函数运行,你可以叫 System.Runtime.CompilerServices.RuntimeHelpers :: RunClassConstructor 明确。


  

由于我们在这里调用的标准,从分区我行,8.9.5这样说:

     

如果标记BeforeFieldInit然后点击类型的初始化方法是在执行,或之前的某个时候,首先访问任何静态字段该类型定义的。

     

这部分实际上将详细介绍如何在语言的实现可以选择prevent你所描述的行为。 C ++ / CLI不选择,而它们允许程序员这样做,如果他们的愿望。

     

基本上,自code以下已经完全没有任何静态字段,JIT正在根本就不是静态调用类的构造函数完全正确

I've recently moved a project I'm working on from .NET 3.5 to .NET 4. I'm using C#, Managed C++ and Unmanaged C++.

In one of my Managed C++ (interop) I'm having a static constructor:

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

In .NET 3.5 once Dequeue() had been called for the first time it would trigger the static initialization, which runs the static constructor. Once I moved to .NET 4.0, the static constructor was never called.

I know there have been changes in static initializations in .NET 4.0, but according to all I read it should work fine.

解决方案

In .NET, type initializers may only be called the first time a field is accessed. This is controlled by the [BeforeFieldInit] attribute.

I filed a bug report, which is only available to beta testers, despite being marked "Public".

Here's the explanation from Microsoft, which you may find helpful:

For C++, this is the intended behavior. We mark our classes with BeforeFieldInit, and so the initialization the CLR is performing is correct. We do not offer a way in C++/CLI to change this behavior. If you require the class constructor to run, you are able to call System.Runtime.CompilerServices.RuntimeHelpers::RunClassConstructor explicitly.


Since we're invoking the standard here, the line from Partition I, 8.9.5 says this:

If marked BeforeFieldInit then the type’s initializer method is executed at, or sometime before, first access to any static field defined for that type.

That section actually goes into detail about how a language implementation can choose to prevent the behavior you're describing. C++/CLI chooses not to, rather they allow the programmer to do so if they wish.

Basically, since the code below has absolutely no static fields, the JIT is completely correct in simply not invoking static class constructors.

这篇关于托管C ++静态构造函数不叫.NET4的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆