Avoiding static variables with Singleton
Solution 1
One way to use a singleton (lifted from http://msdn.microsoft.com/en-us/library/ff650316.aspx)
using System;
public class Singleton
{
private static Singleton instance;
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
/// non-static members
public string Foo { get; set; }
}
Then,
var foo = Singleton.Instance.Foo;
Singleton.Instance.Foo = "Potential thread collision here.";
Note that the instance member is a static field. You can't implement a singleton without using a static variable, and (I seem to recall - it's been awhile) this instance will be shared across all requests. Because of that, it's inherently not thread safe.
Instead, consider putting these values in a database or other persistent store that's more thread-friendly, and creating a class that interfaces with that portion of your database to provide transparent access.
public static class Foo
{
public static string Bar
{
get { /// retrieve Bar from the db }
set { /// update Bar in the db }
}
}
Solution 2
Let's address your statements one at a time:
A colleague of mine told me that I should never use static variables because if you change them in one place, they are changed everywhere.
It seems fairly clear that your colleague means the basic feature of static variables: there is only one instance of a static variable. No matter how many instances of any class you create, any access to a static variable is to the same variable. There is not a separate variable for each instance.
He told me that instead of using static variables I should use Singleton.
This is not good global advice. Static variables and singletons aren't in competition with each other and aren't really substitutes for each other. A singleton is an instance of a class, managed in such a way that only one instance is possible to create. A static variable is similarly tied to exactly one (static) instance of a class, but could be assigned with not only a class instance but any data type such as a scalar. In actuality, to effectively use the singleton pattern, you must store it in a static variable. There is no way to "use a singleton instead of a static variable".
On the other hand, perhaps he meant something slightly different: perhaps he was trying to say that instead of your static class having many different static variables, method, properties and fields (altogether, members) that function as if they were a class, you should make those fields non-static, and then expose the wrapping class as a Singleton instance. You would still need a private static field with a method or property (or perhaps just use a get-only property) to expose the singleton.
I know that Singleton is for limitation of the number of instances of one class to one. How can Singleton help me with static variables?
A static class's variables and a singleton are alike in that they both are to be instantiated once (the former enforced by the compiler and the latter enforced by your implementation). The reason you'd want to use a singleton instead of a static variable inside of a class is when your singleton needs to be a true instance of a class, and not consist simply of the collected static members of a static class. This singleton then gets assigned to a static variable so that all callers can acquire a copy of that same instance. As I said above, you can convert all the different static members of your static class to be instance members of your new non-static class which you will expose as a singleton.
I would also like to mention that the other answers given so far all have issues around thread safety. Below are some correct patterns for managing Singletons.
You can see that an instance of the Singleton
class, which has instance (or non-static) members, is created either by static initialization or within the static constructor, and is assigned to the variable _singleton
.. We use this pattern to ensure that it is instantiated only once. Then, the static method Instance
provides read-only access to the backing field variable, which contains our one, and only one, instance of Singleton
.
public class Singleton {
// static members
private static readonly Singleton _singleton = new Singleton();
public static Singleton Instance => _singleton
// instance members
private Singleton() { } // private so no one else can accidentally create an instance
public string Gorp { get; set; }
}
or, the exact same thing but with an explicit static constructor:
public class Singleton {
// static members
private static readonly Singleton _singleton; // instead of here, you can...
static Singleton() {
_singleton = new Singleton(); // do it here
}
public static Singleton Instance => _singleton;
// instance members
private Singleton() { } // private so no one else can accidentally create an instance
public string Gorp { get; set; }
}
You could also use a property default without an explicit backing field (to follow) or in a static constructor can assign the get-only property (not shown).
public class Singleton {
// static members
public static Singleton Instance { get; } = new Singleton();
// instance members
private Singleton() { } // private so no one else can accidentally create an instance
public string Gorp { get; set; }
}
Since static constructors are guaranteed to run exactly once, whether implicit or explicit, then there are no thread safety issues. Note that any access to the Singleton
class can trigger static initialization, even reflection-type access.
You can think of static members of a class as almost like a separate, though conjoined, class:
Instance (non-static) members function like a normal class. They don't live until you perform
new Class()
on them. Each time you donew
, you get a new instance. Instance members have access to all static members, including private members (in the same class).Static members are like members of a separate, special instance of the class that you cannot explicitly create using
new
. Inside this class, only static members can be accessed or set. There is an implicit or explicit static constructor which .Net runs at the time of first access (just like the class instance, only you don't explicitly create it, it's created when needed). Static members of a class can be accessed by any other class at any time, in or out of an instance, though respecting access modifiers such asinternal
orprivate
.
Solution 3
The whole point of the static
modifier is to ensure that the object thus modified is the same wherever it is used as it requires no instantiation. The name originally came about as a static variable has a fixed location in memory and all items referring to it will reference the same memory location.
Now you may wish to use a static field within a class, in which case it exists before the class is instantiated (constructed). There may be instances where you would want this.
A singleton is a different beast. It is a class that is limited to a single instantiation by use of a private constructor and a static
property. So in that regard you still can't avoid statics by using a singleton.
Solution 4
To answer the stated question:
It is incredibly stupid (but possible) to create a singleton without a static field.
To do it, you need to use someone else's static field, such as AppDomain.GetData
or (in ASP.Net) HttpContext.Application
.
petko_stankoski
Updated on June 11, 2022Comments
-
petko_stankoski almost 2 years
A colleague of mine told me that I should never use static variables because if you change them in one place, they are changed everywhere. He told me that instead of using static variables I should use Singleton. I know that Singleton is for limitation of the number of instances of one class to one. How can Singleton help me with static variables?
-
LoganS over 12 years-1 static doesn't involve any instances - it pertains to a class.
-
SLaks over 12 yearsThat's not true at all. You can't manage the lifetime of a singleton. Singletons do not help you achieve thread safety. All of your claims (true or not) also apply to static fields.
-
and_the_rand over 12 years
-
Steve Rowbotham over 12 years@JonH A static field or property still holds a single instance as its value.
-
LoganS over 12 years@SteveRowbotham that I can agree with- I was more describing a
static class
more then a static member of a class which has one value...ack ambiguity. -
SLaks over 12 years@SteveRowbotham: Wrong. A property does not hold a single instance; it can return whatever it wants. A field can be
[ThreadStatic]
-
ninu over 12 yearsI agree with SLaks above. Read this post from a previous question: Design Patterns When to Use the Singleton
-
Steve Rowbotham over 12 years@SLaks:
[ThreadStatic]
isn't under discussion. The point I was making is straight-forward - whether you expose a static field directly or via a property there is still an instance. -
svick over 12 yearsStatic fields don't exist before a class is created. But you can be sure that it exists before any instance of that class is created.
-
svick over 12 yearsAnd can you explain how does that help alleviate the “problems” static classes have? Also, your code won't compile, I assume you didn't intend to make
Class2
static
. -
petko_stankoski over 12 yearsBut the initial class wasn't static. It was normal class which contains methods and variables. Some of the variables are static.
-
Silas over 12 yearssvick: Saw that mistake too and corrected it already. Thanks anyway.
-
ChrisBD over 12 yearsWhere do I say that it exists before a class is created?
-
svick over 12 yearsYou say it exists “before the class is instantiated (constructed)”. I think that's confusing. Classes aren't instantiated, objects that are an instance of the class are.
-
ChrisBD over 12 yearsMy apologies I thought that by saying "(constructed)" after instantiated that I'd made it clear that a static field exists before a class contructor is executed.
-
svick over 12 yearsAnd that's confusing again. What's a “class constructor”? It could be interpreted as static constructor or instance constructor. Although, you would be right in both cases.
-
ChrisBD over 12 yearsWell what can I say? In practice does it make any difference? The static constructor is only executed once for a given application domain, whereas the class instance constructor may be executed many times, eitherway the static field exists and is initialized before either of the constructors are executed.
-
Suhas over 12 years@jonh There has to be some instance at the core, isn't it? And I was talking more from perspective of control you have over the static as against a singleton.
-
ErikE about 7 yearsExcept, can't you get thread safety by assigning the
instance
variable with a static initializer:private static readonly Singleton instance = new Singleton()
? Then your property can just be:public static Instance => instance;
. The only difference is thatinstance
is assigned the first time theSingleton
class is used in any capacity, not the first timeInstance
is accessed. This is a minor detail, as any problems this causes can be eliminated by moving the code to its own class so any access to the class does occur only when the singleton can be instantiated. -
ErikE about 7 yearsI just confirmed that static initializers are guaranteed to run only once per app domain (be careful with static generics though as that's once per generic type). So using a static method instead of a static initializer or static constructor is not a good idea as it brings with it the non-thread-safe problems you mention.
-
Servy about 7 yearsThe question isn't asking how to create a singleton. This isn't addressing the actual question asked at all.
-
Servy about 7 yearsYou shouldn't be posting an answer to say that the question doesn't make sense. If you think that the question doesn't make sense, vote to close it as unclear, rather than posting an answer to a question you don't think is understandable.
-
ErikE about 7 years@Servy The question as written doesn't make sense, however the asker's confusion is easy to understand and easily correctable. Do you have a resource on meta.stackexchange that supports your position that "the question doesn't make sense as written"? In any case, I will reword to say that the asker's statements make some invalid assumptions, which I can help correct for him.
-
Servy about 7 yearsI don't need to prove to you that the question doesn't make sense. You are the one saying that the question doesn't make sense, both in your answer (on multiple occasions) and in your comment.
-
ErikE about 7 years@Servy I wasn't asking you to prove that the question doesn't make sense. I was trying to ask you why your opinion that "you shouldn't post an answer to say a question doesn't make sense" conforms to community standards in the stackexchange network and on stackoverflow specifically (as I've never heard that before). In any case, I have removed all references to "this doesn't make sense", and in fact, have to thank you for your push-back as I think my answer is now improved--I think I've now hit on the most likely advice the colleague was trying to give and explained how to do that.
-
Servy about 7 yearsYou really need me to explain to you why you shouldn't answer a question that doesn't make sense? There's a specific close reason for questions that don't make sense, "Unclear what you're asking". When it's unclear what a question is asking, you should use that close reason. While you've re-worded your answer, you're still indicating that the question is unclear by saying that you find the question confusing, that you're having to guess at what it's asking, etc.
-
ErikE about 7 yearsI changed my mind. I think the question makes sense now. And I think the question and answer add value, even if the original asker wasn't 100% clear. He was still 80% clear, and explaining the difference between
static
and a singleton should clear up any confusion. -
ErikE about 7 years@Servy Are you going to vote down the other answers on the page that have the same problems mine do (in your mind)? Is there a reason you singled out my answer above the others besides that it is a new answer? If you think the question is that unclear, you can cast your vote to close, right?
-
ErikE about 7 yearsYup, I did notice. So now, my comment helps all those people who come to this question looking for current answers, instead of leaving them in the obsolete/archaic land of trying to use old code on new frameworks! It's a win all around, right? I didn't down-vote you. It was good information for the time.
-
ErikE about 7 yearsIf you like I'll delete and reword to avoid saying "not a good idea" and can say instead "there is now a better way that avoids all thread safety issues".
-
ErikE over 3 yearsThe
GetInstance
method here is not thread-safe and could yield multiple instances of the same class, because another thread's execution ofGetInstance
could also check thatinstance == null
before either thread setsinstance
tonew Class2()
. Best to use static initialization instead of trying to sychronize, which is full of pitfalls.