demaxSH
demaxSH

Reputation: 1815

Any good way for getting a single instance instead of using Singleton (in C#)

I used to use singleton get a single instance, but it was disclaimed by others because of some disadvantage in testing. What's the disadvantage? Is there any alternative good way for getting a global instance?


So is it OK for me to create only one singleton class Global in application as global hub? so that I can put any other class's single instances in Global.Instance.

Upvotes: 2

Views: 650

Answers (4)

ChrisWue
ChrisWue

Reputation: 19070

Ok, why singletons are bad you can read here: What is so bad about singletons?

Specifically for testing: A typical singleton pattern looks like this

class MyClass
{
    private static MyClass m_Instance = new MyClass();
    public static MyClass Instance
    {
        get { return m_Instance; }
    }
}

Now imagine you have to run a whole bunch of tests all involving the MyClass.Instance. This class carries around a state and you usually need to have to have a way to reset it between tests so that each test can start with a clean initial state. Now you can add a Reset() method but that means you add code to your class just for the purpose of being able to test it which is not desirable.

What to use instead: Well, the singleton in itself is not really the bad thing. The problem it leads to is that it makes it easy to write code like this:

class SomeClass
{
    public void SomeMethod()
    {
        ...
        MyClass.Instance.DoSomething();
    }
}

Now you have created an implicit dependency on the singleton instance you cannot easily break. One approach which solves this problem is via dependency injection (which was already mentioned):

class SomeClass
{
    public SomeClass(MyClass myClass)
    {
        m_MyClass = myClass;
    }

    public void SomeMethod()
    {
        ...
        m_MyClass.DoSomething();
    }
}

and you can do:

var someClass = new SomeClass(MyClass.Instance);

in your program and

var someClass = new SomeClass(new MyClass());

for testing.

So singletons are not that bad and sometimes the right tool for the right job, however you need to be careful of how you use them.

Upvotes: 4

Can Gencer
Can Gencer

Reputation: 8885

Consider using the what is called "ambient context" pattern instead. This example is taken from Mark Seeman's excellent Dependency Injection in .NET book. This pattern gives you the ease of use of a singleton, and also testability. The important point here is the existence of what is called a good "default" (i.e. DefaultTimeProvider shown in the example). Another thing to consider is not to abuse this pattern, in most cases you can inject the different dependencies into the constructor of the class. This pattern should only be used for concerns that cross cut throughout the whole application.

public abstract class TimeProvider
{
    private static TimeProvider current;
    static TimeProvider()
    {
        TimeProvider.current = new DefaultTimeProvider();
    }
    public static TimeProvider Current
    {
        get { return TimeProvider.current; }

        set
        {
            if (value == null)      
            {         
                throw new ArgumentNullException("value");    
            }              
            TimeProvider.current = value; 
        }
    }
    public abstract DateTime UtcNow { get; }
    public static void ResetToDefault()
    {
        TimeProvider.current = new DefaultTimeProvider();
    }
}

Upvotes: 0

Numan
Numan

Reputation: 3948

Testability is the main difficulty as I can see, to address that to some extent, we have unity containers.
Check Unity container http://unity.codeplex.com/

Upvotes: 1

NickD
NickD

Reputation: 2646

i dont see any issues with testability and singletons. also i dont see how DI can replace them.

Upvotes: 0

Related Questions