logeeks
logeeks

Reputation: 4979

singleton pattern in C# Question

I was researching on the singleton pattern for C# I found this example from the msdn website.

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

   private Singleton(){}

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

Because the Singleton instance is referenced by a private static member variable, the instantiation does not occur until the class is first referenced by a call to the Instance property. This solution therefore implements a form of the lazy instantiation property, as in the Design Patterns form of Singleton.

I am not pretty sure when will the memory will get allocated to

private static readonly Singleton instance 

1)Will it happen when the Instance property is called or even before it?

2) I need to force the class to create a new memory sometimes to purge its content. Is it safe to do so using set ?

set
{
instance = null;
}

Upvotes: 1

Views: 2968

Answers (5)

FilipRot
FilipRot

Reputation: 83

Static members are initialized before the static member is accessed for the first time, and before the static constructor, if any is called.

Read more on MSDN

Upvotes: 0

Vlad
Vlad

Reputation: 35594

In the example code you provided, the singleton instance will be created at the time of the first access to the class. This means for your example at the time when Instance gets called for the first time.

More insight you can find in Jon Skeet's article Implementing the Singleton Pattern in C#, see Method 4.

Basically, in order to achieve truly lazy behaviour something like

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

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

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

is enough.

(But anyway, the full and much better overview can be found in the mentioned article.)

EDIT
Actually, as it follows from the mentioned article, the instance is not guaranteed to be created at the first access, because of BeforeFiledInit mark. You need to add an empty static constructor, this way it's guaranteed to be lazy. Otherwise the instance will get created at some unspecified time between the program start and first access. (.NET runtime 2.0 is known to have more eager strategy, so you'll probably not get the lazy behaviour.)

Quoting from the said 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 [...] marks all types which don't have a static constructor [...] as beforefieldinit.

EDIT 2
If you want the singleton object to clean up, you should include this functionality into the class Singleton itself.

Removing the property value will effectively make your class not a singleton any more! Imagine that someone accesses the singleton and gets the singleton instance. After that you set the property to null. The existing object of the Singleton class won't disappear, because there's still a reference to it! So the next time you access the Instance property, yet another instance of the Singleton class would be created. So you lost two things: your object is not a singleton any more (because you have got 2 instances existing at the same time), and the memory hasn't been cleared either.

Upvotes: 7

CodesInChaos
CodesInChaos

Reputation: 108880

The C# specification says:

10.5.5.1 Static field initialization

The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. If a static constructor (§10.12) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

i.e. They only guarantee you get is that it happens before the instance field is read. But it can happen much earlier.

If you want to guarantee that it that it doesn't run earlier than the first access of the property you'll need to add a static constructor(potentially empty):

The static constructor for a closed class type executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
· An instance of the class type is created.
· Any of the static members of the class type are referenced.


As a side node: I noticed that when using DI it is rarely necessary to use an actual singleton. Simply telling DI that it should create a single instance is enough. This is very nice if you decide at a later point that you want more than one instance, since then the fact that it's a singleton isn't baked into all the code using it.

Upvotes: 3

Samuel Neff
Samuel Neff

Reputation: 74949

The singleton instance will be loaded into memory when the class itself is loaded which is when the method which could call it begins execution. The actual line that calls into the class doesn't have to actually execute. This is a very slight distinction but can create hard-to-debug problems when a static constructor or static field initializer can throw an error (which you don't have here).

This is fixed in .NET 4 with the new Lazy<T> implementation.

http://msmvps.com/blogs/jon_skeet/archive/2010/01/26/type-initialization-changes-in-net-4-0.aspx

public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy =
        new Lazy<Singleton>(() => new Singleton());

    public static Singleton Instance { get { return lazy.Value; } }

    private Singleton()
    {
    }
} 

http://csharpindepth.com/Articles/General/Singleton.aspx

Upvotes: 7

mdm
mdm

Reputation: 12630

It says in the quote you posted:

the instantiation does not occur until the class is first referenced by a call to the Instance property

So... Whenever you call .Instance, or at some point before.

Upvotes: 0

Related Questions