The use of static properties is certainly nothing new, but every time I demonstrate some of the ways I use Statics in conjunction with Static constructors at a conference there are a lot of folks who have not used this technique to manage global state in applications.
Static properties are essentially properties that are global to all instances of a given object instance. Statics are not accessible on the instance itself but rather are a single store of memory that is referenced through the class name. So rather than creating an instance and assigning a value to an instance property you use the name of the class and the property.
Public class Statics
{
Public static string MyStatic;
}
Then in code this is referenced simply by:
Statics.MyStatic = “hello World”;
Notice that I don’t have to instantiate the Statics class first. In fact, if you do instantiate the class and then look for a property called MyStatic on the instance it’s not there. You have to reference the static through the classname.
In Visual Basic statics are called Shared properties which provide the same characteristics. I’ll use C# syntax here but it’s pretty much interchangeable with Shared in VB.
Because statics are not tied to an instance but rather the class itself they are essentially global. Code from anywhere in the application can access these static properties. This also means that you have to be careful with them in a multi-threaded environment such as ASP. Net or from multi-threaded code of your own.
Static Constructors
Where things get really interesting is with Static constructors. If you need to initialize a static property you have to do in a static constructor. Static constructors are special constructors of an object that fires the first time a static variable in that level of the class hierarchy is accessed. Note that this means that these constructors are not inherited! They apply exactly to the level of the class that they are attached to. Further you cannot call a static constructor explicitly so there’s no base() call that you can make from an inherited constructor. This is because statics essentially don’t inherit anything. They’re really just independent variables that are scoped via syntax into the semi-context of a class.
public static Statics()
{
MyStatic = “Time is: “ + DateTime.Now.ToString();
}
So, static constructors fire the first time you access any static property on the class. Static constructors fire exactly once namely the first time a static property is accessed, regardless of the thread that calls it. The constructor will not fire again (at least in the current AppDomain). This makes statics very useful because you now have a mechanism to store global state and be guaranteed that this state initializes the first time any of the static properties are accessed.
Although you should avoid using ‘globals’ as much as possible there are always a few things in an application that you want cached. Even if you’re using ASP. Net which includes a powerful Cache object, statics properties often make a better choice because they are strongly typed and they are not stored in some collection and perform optimally.
I use statics for a number of things that cache information about an application. For this purpose I usually have one object in my application called App that holds these static properties. I usually put this class in my main application’s namespace so I can access any of its properties with:
App.MyCustomProperty
From anywhere in the application (including ASP.Net script code and <%= %>expressions).
My most common use for this feature is with a Configuration object in my application. I store all configuration settings in a custom class as properties. Every setting has a property entry. The Configuration class then takes all those properties and persists them into the application’s .Config file. When first loaded the properties are re-loaded from the .Config file.
Statics and specifically static constructor make this scenario viable, so rather than having to reload this object every time, I simply create a reference to it as a static property on my App object:
public class App
{
public static WebStoreConfig Configuration;
static App()
{
/// *** Load the properties from the Config file
Configuration = new WebStoreConfig();
}
}
The object is now globally available. From anywhere in the app I can do:
string AppName = App.Configuration.ApplicationName;
I can also use it in ASP tags:
<%= Westwind.WebStore.App.Configuration.WebStoreName %>
In ASP. Net applications an added bonus of the static design factor is that the static constructor will fire again when the ASP. Net app restarts itself, for example due to changes to Web.Config. Because changes to the web.config file cause ASP. Net to restart the application your configuration object automatically stays synced because it too will be reloaded when a first access is made to the static property.
Other things I store in statics are things that I need to cache on a regular basis. If you have certain lookup tables that are frequently reused – you can simply cache these as well. You can use a DataSet or DataTable easily in this fashion. Load the Data in the static constructor then simply use the static reference to the data when needed.
When using statics in this fashion however you have to always remember that there’s the potential that multiple threads will access this data simultaneously. In fact, if you’re using statics in ASP. Net is very likely that they will be called off multiple threads as ASP. Net requests come in on multiple simultaneous threads all the time. If you only read data then this is not much of an issue, but if you write data as well or you store objects that internally manage data you need to be real careful.
Don’t try this at home
For example one failed experiment of mine was to try and cache SqlCommands that are generated by the CommandBuilder in a static property. Actually I used a cached DataAdapter for this. I tried it out hooked up the code to load the Command objects in the Data Adapters (one for each bus object) and stored them in static properties. The business object in their constructors then picked up these ‘cached’ pre-configured instances. Sounds reasonable on the first look and sure enough it appeared to work fine in my basic testing at first even in ASP. Net apps. However, as soon as I started loading the app I realized that failures were occurring. Why? Well, clearly you’re recycling Command objects and in this case the same Command object might be shared by two instances trying to run a query on separate threads. What happens there? Connections get assigned possibly from two separate threads or a connection gets assigned and another object actually gets those command objects to run the DataAdapter.Update() with. All of a sudden now have a classic multithreading nightmare scenario where data is being updated from two threads that don’t know about each other.
This is an extreme example of oversight on my part and the result of staying up too late one night long beyond any reasonable quitting time. But the moral here is: be sure you know what you’re caching and be sure you know what any classes that you store in this fashion do and that they are thread safe. With simple properties or objects that are plain instances you likely will not have any issues. And even if you do, you can always use the Lock() command block to synchronize access. But more complex objects – especially data objects which seem to lend themselves well to some sort of caching – do things internally that might bite you later. Make sure you test multi-threaded scenarios especially under ASP. Net. Typically objects that are serializable are safe in this fashion.
Caching or Static
So should you always use statics? Or should you use the Cache object in ASP. Net? The Cache object in ASP. Net (or even the Microsoft Caching Application Block) allow more flexibility in how and when objects are stored and the cache also automatically handle synchronization of objects into the cache so you don’t have to make sure that you place the appropriate lock() commands around it. The Cache object also has the ability to track items in the cache with Cache Dependencies which allow you to be notified when a dependency changes. If you have dependencies then the Cache is probably a better choice.
My basic rule for using Statics as globals is this: The data should be truly static – meaning it only needs to be written once (or very few times in controlled conditions) preferably in the constructor because that’s synchronized automatically. There should be a good reason that you are using a Static variable over say the Cache object. Strong typing and automatic type conversion, defaults and error checking in the Configuration object were my main objectives in using a static instance for this object.
?>
Other Posts you might also like