13

I'm trying to understand why this is a correct implementation of the Singleton pattern:

public sealed class Singleton : ISingleton
{
    public static Singleton Instance { get; } = new Singleton();

    private Singleton() { }

    // methods
}

What about the beforefieldinit flag? According to Jon Skeet article:

The laziness of type initializers is only guaranteed by .NET when the type isn't marked with a special flag called beforefieldinit. Unfortunately, the C# compiler (as provided in the .NET 1.1 runtime, at least) marks all types which don't have a static constructor (i.e. a block which looks like a constructor but is marked static) as beforefieldinit.

Is the static constructor not needed in the newest version of C#?

The code above is the implementation of SystemClock in NodaTime project, by Jon Skeet.'

EDIT Jon Skeet code for reference (why I'm mentioning this beforefieldinit flag):

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}
ebvtrnog
  • 4,167
  • 4
  • 31
  • 59
  • What about that flag? I don't understand the question. – usr Mar 21 '16 at 14:49
  • @usr see the edit :) – ebvtrnog Mar 21 '16 at 14:51
  • There is an outstanding C# language design issue for explicitly specifying `beforefieldinit` behavior: https://github.com/dotnet/roslyn/issues/4448 (fyi) – usr Mar 21 '16 at 14:52
  • Roslyn online says that the type gets marked as beforefieldinit: http://tryroslyn.azurewebsites.net/#f:r/A4VwRgNglgxgBAZwKYEMJICZxhFCFwDKUAdgOboAuA9iQFADedcLcoksilKlnx5VWnACSJBNxIwkcBnDJJKAbjgBfOAF44JJAHcipCgtoAKAJSK6zVsABOUAG49p/QzRJmZqy6zgB6X3AAtgoAFtQYCHQqQAAA== – usr Mar 21 '16 at 14:56
  • The issue with `beforefieldinit` refers to the *laziness* of instantiation of the instance, not to whether or not the implementation is a correct and safe singleton. There's a "Performance vs laziness" section of the same Jon Skeet post you refer to that goes into some more detail as to why you may care about laziness, or not. – Preston Guillot Mar 21 '16 at 14:57

1 Answers1

11

Both are correct singleton implementations. Whether you need the static constructor just depends on how much you care about full laziness. If you really, really don't want the singleton to be instantiated until it's used by a caller, you should have a static constructor - or use Lazy<T>. You can use a static constructor in the C# 6 code as well, of course:

public sealed class Singleton : ISingleton
{
    public static Singleton Instance { get; } = new Singleton();

    static Singleton() { }
    private Singleton() { }

    // methods
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • now compiler does not marks by default static constructor beforefieldinit right? – Ehsan Sajjad Mar 21 '16 at 16:09
  • @EʜsᴀɴSᴀᴊᴊᴀᴅ: I'm not aware of any change on that front, but I'll check. – Jon Skeet Mar 21 '16 at 16:10
  • @EʜsᴀɴSᴀᴊᴊᴀᴅ: I suggest you ask a new, very specific question then. I've just confirmed that the C# compiler still adds `beforefieldinit` unless there is a static constructor. – Jon Skeet Mar 21 '16 at 16:12
  • @EʜsᴀɴSᴀᴊᴊᴀᴅ: Sure, I don't think I'd ever suggested it would be null. It just affects the timing of when the type initializer is executed. – Jon Skeet Mar 21 '16 at 16:30
  • I tried with and without the static constructor and it seems opposite from what you write? without the static ctor when calling static method it won't initialize the fields, with the static ctor it always initialize them - I've just added a Stub static method which returns hard coded string - whenever I add the static ctor it always prints the console write I've added to the private ctor even if I just call Singleton.Stub(), if I comment the static ctor it doesn't initialize "Instance" and doesn't call the private ctor (tested in release mode .NET 4). – BornToCode May 24 '16 at 13:45
  • @BornToCode: I suggest you ask a new question with the actual code, so I can explain the behaviour. It partly depends on what that static method does. – Jon Skeet May 24 '16 at 13:47
  • @JonSkeet - Thank you, I just did. It's [here](http://stackoverflow.com/q/37415882/1057791). – BornToCode May 24 '16 at 14:01
  • @JonSkeet `public static Lazy Instance => new Lazy(() => new Singleton());` So, in C#6 full laziness can be achieved like this? – Givi Nov 29 '17 at 12:26
  • @Givi: No, that would give you a new Singleton each time you used the property. But you could use `public static Lazy Instance { get; } = new Lazy(() => new Singleton());` - you may still want a static constructor though, and returning a `Lazy` rather than a `Singleton` probably isn't ideal either. – Jon Skeet Nov 29 '17 at 12:55