What's the difference in these ways of creatin

2019-03-10 08:20发布

问题:

I have had a bug recently that only manifested itself when the library was built as a release build rather than a debug build. The library is a .NET dll with a COM wrapper and I am using CoCreateInstance to create a class from the dll in an unmanaged c++ app. When I finally tracked the bug down it was caused by accessing a singleton object. I had the singleton instance declared like so:

private static readonly MyObjectType s_instance = new MyObjectType;

and then accessed it with:

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

this was failing. Changing it to:

private static MyObjectType s_instance;

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

fixed the issue. Any ideas why the initial usage didn't work and if there are any downsides to doing it either way?

The release dll seemed to be perfectly usable from another managed app.

回答1:

Try adding an (empty) static constructor, or initialize the singleton in a static constructor.

Jon Skeet has a full discussion of singleton patterns here. I'm not sure why it failed, but at a guess it could relate to the "beforefieldinit" flag. See his 4th example, where he adds a static constructor to tweak this flag. I don't claim to be an expert on beforefieldinit, but this symptom seems to fit some of the symptoms discussed here.



回答2:

Just reiterating what Marc Gravell said, but it sounds a lot like a beforefieldinit problem, which means the empty static constructor is your solution. You'd need to post any and all constructors in the class to get a definitive answer.

The second method has the advantage of lazy loading (where that is an advantage).