Channels ▼

Arnon Rotem-Gal-Oz

Dr. Dobb's Bloggers

Singleton in .NET

April 01, 2008

While I personally don't like the Singleton pattern too much (it is essentially an OO mask for Global Variables, which makes it harder to unit test etc.), I still need to use it now and then. Anyway, I saw a post by Jack Altiere about Using the Singleton Pattern in .NET and since it presents an implementation that leaves a lot to be desired, I decided to comment on that.

For one thing, Jack presents a solution which locks every time the singleton is accessed (see below). The reason this is flawed is that singletons are instantiated once, but are accessed a lot of times and with this implementation you pay every time you try to access the singleton:

<span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px"><br /><span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px">//bad implementation - don't use</span><br /><span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px">//also note some initialization etc. is omitted for brevity</span><br /> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">public</span> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">static</span> Foo Instance<br />{<br />      get<br />       {<br />        <span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px">// This lock allows thread safety.</span><br />             <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">lock</span> (_mutex)<br />             {<br />                   <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">if</span> (_instance == <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">null</span>)<br />                        _instance <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px">=</span> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">new</span> Foo();<br />                  <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">return</span> _instance;<br />            }<br />      }<br />   }</span>


There's a better "standard" way to do that which basically means you check if the the instance is null, lock, then check again (in case more than one thread got past the first check ) and only then instantiate (you'd also need to mark the instance volatile, in this case).


.NET has a better way to create thread-safe singletons by merely using a static readonly declaration as in:

<span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">public</span>  <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">sealed</span> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">class</span> singleton<br />{<br />        <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">public</span> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">static</span> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">readonly</span> MySigleton Instance <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px">=</span> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">new</span> MySingleton()<br />}</span><br /><br />

This implementation is not as lazy as the implementations above -- but it is thread safe and efficient (you can get more laziness if you use a nested class as described here).

But that's not all. See, one of the problems of the Singleton pattern (besides those mentioned above) is that it is also a violation of the Single Responsibility Principle (SRP; see OO primer). You can solve this problem if you use Generics and create something like C++'s template-based Singleton class:
<pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">namespace</span> ConsoleApplication5<br />{<br />    <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">class</span> Singleton<T> where T : <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">new</span>()<br />    {<br />        <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">private</span> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">static</span> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">readonly</span> T inst <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px">=</span> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">new</span> T();<br /><br />        <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">public</span> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">static</span> T Instance<br />        {<br />            get { <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">return</span> inst; }<br />        }<br />    }<br />}<br /><br /><br /></span>

 and then use that simply by doing something like Singleton<MyClass>Instance 

[update]
Eran points out that Jack's code is not only inefficient but also not thread safe (see Eran's post on the subject). Basically you need to make the instance variable volatile just like in the double check scenario.

Reshef points to the  Static Gateway Pattern as an alternate  way to get the singleton effect. While we are talking about other possibilities, I should have probably mentioned that the usual way I handle situation where I need a single instance is instantiating one instance on the main/loader thread and then just using dependency injection... :)

 

 

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video