0
votes

I'm implementing a singleton pattern, and need the initialization to be thread safe.

I've seen several ways to do it, like using the double check lock implementation, or other techniques (i.e.: http://csharpindepth.com/articles/general/singleton.aspx)

I wanted to know if the following approach, which is similar to the fourth version in the article, is thread safe. I'm basically calling a method in the static field initializer, which creates the instance. I don't care about the lazyness. Thanks!

public static class SharedTracerMock
{
    private static Mock<ITracer> tracerMock = CreateTracerMock();

    private static Mock<ITracer> CreateTracerMock()
    {
        tracerMock = new Mock<ITracer>();
        return tracerMock;
    }

    public static Mock<ITracer> TracerMock
    {
        get
        {
            return tracerMock;
        }
    }
}
1

1 Answers

3
votes

Yes, that's thread-safe - although it's not the normal singleton pattern, as there are no instances of your class itself. It's more of a "single-value factory pattern". The class will be initialized exactly once (assuming nothing calls the type initializer with reflection) and while it's being initialized in one thread, any other thread requesting TracerMock will have to wait.

Your code can also be simplified by removing the method though:

public static class SharedTracerMock
{
    private static readonly Mock<ITracer> tracerMock = new Mock<ITracer>();

    public static Mock<ITracer> TracerMock { get { return tracerMock; } }
}

Note that I've made the field readonly as well, which helps in terms of clarity. I generally stick trivial getters all on one line like this too, to avoid the bulk of lots of lines with just braces on (7 lines of code for one return statement feels like overkill).

In C# 6, this can be simplified even more using a readonly automatically implemented property:

public static class SharedTracerMock
{
    public static Mock<ITracer> TracerMock { get; } = new Mock<ITracer>();
}

Of course, just because this property is thread-safe doesn't mean that the object it returns a reference to will be thread-safe... without knowing about Mock<T>, we can't really tell that.