Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Global Statics and Static Constructors


:P
On this page:

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.

?>


The Voices of Reason


 

Jeff Leason
December 20, 2003

# re: Global Statics and Static Constructors

Rick, can you help me out on this business?

I'm trying this, but it's not working if I try to do it like you are where you have a Configuration class in the App class.

Can you give an example of the WebStoreConfig class and properties and its constructors?

Thanks

Rick strahl
December 20, 2003

# re: Global Statics and Static Constructors

Jeff, the Configuration class is just a standard class. It has a normal non-static, constructor and the constructor that is fired off the App object's static constructor. The static that drives this is App.Configuration member, which is static and thus fires the App object's static constructor the first time the Configuration class (actually the App class) is accessed.

FWIW, I will write this Configuration class up formally into an article shortly...

Jeff Leason
December 21, 2003

# re: Global Statics and Static Constructors

Tahnks! I was having problems with where to put "Public" and where not to. And same for "Static".

Rick strahl
December 21, 2003

# re: Global Statics and Static Constructors

Jeff, it's always scope then static. Usually statics are public so it's public static string MyClass.

Jack
April 14, 2005

# re: Global Statics and Static Constructors

T-h-a-n-k---y-o-u! Really. THANK YOU. If you were here I would hug you. I am a college student working on a Java program... and I have been having the worst time with an error that said: "non-static variable choice cannot be referenced from a static context"

I have been sitting here for TWO hours trying to figure this out. It boils down to the fact that the main class of my Java app is not instantiated, and so, in a technical sense, the variable I was trying to use did not exist. But it was SO hard for me to figure out how to just get the darn thing instantiated. And then I came to your page and saw these beautiful lines (designated between the two sets of equal signs:
==============================
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”;

==============================
I applied that concept into my Java program and whoosh, all was suddenly functioning perfectly. Really, I can't thank you enough. THANK YOU. It was so frustrating to sit here trying one thing after another and getting nowhere! God bless you. :)

dhananjaneyulud
January 17, 2006

# re: Global Statics and Static Constructors

great article

Suresh
August 11, 2006

# re: Global Statics and Static Constructors

Rick,

I have a question about this point.
"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)"

What if I need to update the static property say when my configuration change.. or I need to run the static constructor more than once without iisreset?

I need to create one website programmatically for every year. I dont want my code to check of the year(say 2006) exists every time I've something to do with that site.

So, I'm wondering if I can create a static property CurrentSite which will be set to true in the static constructor

public static string CurrentSite;
static constuctor XX
{
if (CurrentSite != current year)
{
Create current year Site from today's date
CurrentSite = currentYear
}
}

but this will not help for the next year if the static constructor is not fired again.

Any idea?

Thanks,
Suresh.


Rick Strahl
August 11, 2006

# re: Global Statics and Static Constructors

You don't need a static constructor for that. Use a static method.



Dave
October 10, 2008

# re: Global Statics and Static Constructors

Suppose you have a class with a static property with only a get (read only). You also have code in a static constructor that sets these properties but takes 1 hour to run.

Now suppose a request comes in at 11:00 am and tries to read from this property. It will need to wait an hour until the page loads which is fine. If a second request on another thread at 11:01 am comes in and tries to read the same property, will it wait until the static constructor is finished? I'm hoping it does... If it doesn't then the 2nd request will read dirty data from un-initialized properties.

In my scenerio, the static constructor runs much quicker, but it's a high traffic mission critical financial application that must read the info correctly.

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2025