【问题标题】:What's the difference in these ways of creating the static instance for a singleton?这些为单例创建静态实例的方式有什么区别?
【发布时间】:2010-09-18 02:11:01
【问题描述】:

我最近遇到了一个错误,该错误仅在将库构建为发布版本而不是调试版本时才表现出来。该库是一个带有 COM 包装器的 .NET dll,我正在使用 CoCreateInstance 从非托管 c++ 应用程序中的 dll 创建一个类。当我最终追踪到这个错误时,它是由访问单例对象引起的。我有这样声明的单例实例:

private static readonly MyObjectType s_instance = new MyObjectType;

然后通过以下方式访问它:

public static MyObjectType Instance 
    { 
        get 
        {                               
            return s_instance; 
        } 
    } 

这失败了。将其更改为:

private static MyObjectType s_instance;

public static MyObjectType Instance 
    { 
        get 
        {               
            if (s_instance==null) 
            { 
                s_instance = new MyObjectType(); 
            } 
            return s_instance; 
        } 
    } 

解决了这个问题。任何想法为什么初始使用不起作用,以及这样做是否有任何缺点?

发布 dll 似乎完全可以从另一个托管应用程序中使用。

【问题讨论】:

  • 这个错误是如何表现出来的?它崩溃了吗?有错误信息吗?
  • 对 CoCreateInstance 的调用每次都返回“ClassNotRegistered”。但仅在发布版本中。在调试版本中一切正常。
  • 是的,这就是我对更改它不满意的原因。该修复程序已升级为仅添加一个静态构造函数。这在 com 中仍然有效,这意味着我可以将实例保持为只读并且仍然是线程安全的。

标签: .net com singleton


【解决方案1】:

尝试添加一个(空的)静态构造函数,或者将单例初始化为静态构造函数。

Jon Skeet 对单例模式 here 进行了完整的讨论。我不确定它为什么失败,但猜测它可能与“beforefieldinit”标志有关。请参阅他的第 4 个示例,其中他添加了一个静态构造函数来调整此标志。我并不声称自己是 beforefieldinit 方面的专家,但这个症状似乎符合 here 讨论的一些症状。

【讨论】:

  • 我什至不知道有静态构造函数之类的东西。感谢您(不知不觉地)教育我!
  • 宾果游戏。添加一个空的静态构造函数解决了这个问题。谢谢。我生命中的 2 天我永远不会回来了。
【解决方案2】:

只是重申 Marc Gravell 所说的,但它听起来很多 像 beforefieldinit 问题,这意味着空的静态构造函数是您的解决方案。您需要在类中发布所有构造函数以获得明确的答案。

第二种方法具有延迟加载的优势(这是一个优势)。

【讨论】:

  • 确实,正如我上面所说,添加静态构造函数是解决方案。
猜你喜欢
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 2011-04-01
  • 2012-08-13
相关资源
最近更新 更多