223
public sealed class Singleton
{
    Singleton() {}

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested() {}
        internal static readonly Singleton instance = new Singleton();
    }
}

I wish to implement Jon Skeet's Singleton pattern in my current application in C#.

I have two doubts on the code

  1. How is it possible to access the outer class inside nested class? I mean

    internal static readonly Singleton instance = new Singleton();
    

    Is something called closure?

  2. I am unable to understand this comment

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    

    what does this comment suggest us?

CuriousGuy
  • 3,818
  • 4
  • 24
  • 28
amutha
  • 2,263
  • 2
  • 14
  • 3
  • 13
    haha I thought I had said that was a bit worried lol... turned out to be a different John Nolan – John Antony Daniel Nolan Aug 14 '12 at 09:17
  • 2
    @thepirat000 - If he was only a participant on SO/Meta, I might disagree, but he does have enough influence in the actual world of programming that that might actually be legit - I'm sure someone has created it at one point or another. – Code Jockey Jun 12 '15 at 14:37
  • 8
    This question's taxonomy is being discussed on [meta](http://meta.stackoverflow.com/questions/316714/user-name-tag-in-question). – BoltClock Feb 12 '16 at 09:58

2 Answers2

366
  1. No, this is nothing to do with closures. A nested class has access to its outer class's private members, including the private constructor here.

  2. Read my article on beforefieldinit. You may or may not want the no-op static constructor - it depends on what laziness guarantees you need. You should be aware that .NET 4 changes the actual type initialization semantics somewhat (still within the spec, but lazier than before).

Do you really need this pattern though? Are you sure you can't get away with:

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();
    public static Singleton Instance { get { return instance; } }

    static Singleton() {}
    private Singleton() {}
}
Sebastian Krysmanski
  • 8,114
  • 10
  • 49
  • 91
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    @JonSkeet - just to cofirm; R# is complaining about empty static ctor, so does it cause any issue if I move the initialization of the instance variable in the static ctor? – Anindya Chatterjee Jul 24 '11 at 07:34
  • 12
    @Anindya: Nope, that's fine. You might want to mail JetBrains to complain though :) – Jon Skeet Jul 24 '11 at 07:40
  • 2
    @JonSkeet, I just raised a concern to JetBrains about this (# RSRP-274373). Let's see what they can come up with. :) – Anindya Chatterjee Jul 24 '11 at 08:33
  • @JonSkeet How can we use destrutor or dispose with the code – Moons May 25 '15 at 13:03
  • 3
    @Moons: You don't. A singleton lives for the duration of the AppDomain. – Jon Skeet May 25 '15 at 14:04
  • 2
    @JonSkeet Any reason not to use `Lazy` so that you don't have to declare a static constructor for the magic `BeforeFieldInit` side-effect? – Ed T Jun 01 '15 at 19:03
  • 3
    `FieldBeforeInit` is `MahaBharata` from `Microsoft` – Amit Kumar Ghosh Jun 01 '15 at 19:05
  • @JonSkeet : I was curious about the Lazy comment as well – Michael Petch Dec 21 '15 at 15:35
  • 1
    @Michael: Nope, it's fine to use Lazy assuming you're on a platform supporting it. (I wrote the article long before Lazy cane along...) Be careful to specify the relevant option to guarantee single initialisation though. – Jon Skeet Dec 21 '15 at 16:22
  • 1
    @JonSkeet: I have through this link ,But i couldnot understand it what is the use of static Constructor :http://csharpindepth.com/Articles/General/Singleton.aspx – Sudhir.net Jun 10 '16 at 04:33
  • @JonSkeet Thanks I've just gone to have a play around and found the error "Access modifiers are not allowed on static constructors". – Harag Jun 16 '16 at 13:37
  • 1
    @harag: Well that's another reason why it wouldn't work, yes. But it's important that you understand the difference between static constructors (automatically called by the CLR when a type is used) and instance constructors (called by user code). – Jon Skeet Jun 16 '16 at 13:38
  • @JonSkeet What do you think about that memory barrier statement below? IIRC, locks do create an implicit memory barrier. And about the deadlock in singleton #6? – El Mac Jan 12 '18 at 11:06
  • @ElMac: I'd have to look more carefully some time, taking a very long time to check. There are far more subtleties with memory barriers than many people realize, and I'm not an expert either. As for deadlocks - I don't know exactly what would be causing a deadlock here. I don't like singletons usually, but not because of deadlocks. – Jon Skeet Jan 12 '18 at 12:11
  • @JonSkeet Ok, thank you. It's just out of curiosity. Concurrency in general is a complex topic, specially with Singletons. – El Mac Jan 14 '18 at 09:57
  • looks like antipattern ... https://learn.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/ – lazydeveloper Jan 28 '18 at 17:20
  • @lazydeveloper: Which part is an antipattern? Personally I *usually* regard singletons as anti-patterns, but you linked to an article *recommending* the use of a singleton. – Jon Skeet Jan 28 '18 at 17:22
  • @JonSkeet i mean ,singleton fixed anti-pattern/improper instantiate issue.I am using it now. – lazydeveloper Jan 28 '18 at 18:31
  • @lazydeveloper: I still don't really understand what you're asking. Sometimes a singleton is reasonable, although personally I find it's *usually* a bad idea. – Jon Skeet Jan 28 '18 at 20:30
  • @JonSkeet what's best idea for instanciate HttpClient objects. I am using singleton pattern. Is it good idea? – lazydeveloper Jan 29 '18 at 06:25
  • 1
    @lazydeveloper: It makes it harder to provide the client for test purposes, but it should work. We can't really say without more context, which is offtopic for this question. If you're still concerned, I would ask a new question, after checking for duplicates. – Jon Skeet Jan 29 '18 at 06:43
50

Regarding question (1): The answer from Jon is correct, since he implicitly marks the class 'Nested' private by not making it public or internal :-). You might as well do it explicitly by adding 'private':

    private class Nested

Regarding question (2): basically what the post about beforeinitfield and type initialization tell you is that if you have no static constructor, the runtime can initialize it at any time (but before you use it). If you do have a static constructor, your code in the static constructor might initialize the fields, which means that the runtime is only allowed to initialize the field when you ask for the type.

So if you don't want the runtime to initialize fields 'proactively' before you use them, add a static constructor.

Either way, if you're implementing singletons you either want it to initialize as lazy as possible and not when the runtime thinks it should initialize your variable -- or you probably just don't care. From your question I suppose you want them as late as possible.

That brings met to Jon's post about singleton's, which is IMO the underlying topic of this question. Oh and the doubts :-)

I'd like to point out that his singleton #3, which he marked 'wrong', is actually correct (because lock's automatically implies a memory barrier on exit). It also should be faster than singleton #2 when you use the instance more than once (which is more or less the point of a singleton :-) ). So, if you really need a lazy singleton implementation, I'd probably go for that one - for the simple reasons that (1) it's very clear for everyone that reads your code what is going on and (2) you know what will happen with exceptions.

In case you're wondering: I would never use singleton #6 because it can easily lead to deadlocks and unexpected behavior with exceptions. For details, see: lazy's locking mode, specifically ExecutionAndPublication.

Dog Ears
  • 9,637
  • 5
  • 37
  • 54
atlaste
  • 30,418
  • 3
  • 57
  • 87