Geeks With Blogs
Blog Moved to http://podwysocki.codebetter.com/ Blog Moved to http://podwysocki.codebetter.com/
Two days ago I posted about the Static Members Best Practices, I now realize I might need to step back just a little bit and get into the debate of why to have static members in the first place.  It's an interesting debate worth having especially when it comes to your designs.
 
Why Use Static Members?
 
 When I have conducted code reviews in the past, I found many times that people would use static methods and properties all over the place.  The only real justification that was used was that it cut down on the lines of code.  To me, that's never really a good justification unless there is some other good reason to do this.  They've told me that they cut down on three lines of code to make it all work in one line.  This brings up another issue of readability and reusability at that point.
 
For example, say we have an event logger class.  Below is an example of the code:
 
public class Logger
{
     public static void LogEvent(string eventSource, string eventMessage)
     {
          if(!EventLog.SourceExists(eventSource))
              EventLog.CreateEventSource(eventSource, "Application");
 
          EventLog log = new EventLog("Application");
          log.Source = eventSource;
          log.WriteEntry(eventMessage);
     } // method - LogEvent
} // class - Logger
 
Now, what's wrong with this code?  Nothing the way it was written, but if we want true overriding capabilities, we probably shouldn't use this code.  But if we expect to write it once and not need any overriding, then it should be fine. 
 
So, when do we use static methods?  Well, for utility method, it makes perfect sense.  Take such examples in the .NET Framework:
*  AppDomain.CreateDomain(string)
*  DateTime.Parse(string)
 
The DateTime.Parse method makes total sense because it creates an instance of a DateTime structure from the incoming string value.  The same goes for AppDomain.CreateDomain.  Follow some common design patterns for real guidance in this.
 
We should also be aware of threading issues.  If we have any static member variables, we need to make sure there are no race conditions exist.  Take for instance the code below:
 
public class Logger
{
     private static Logger instance;
 
     public static Logger Instance
     {
          get
          {
               if(instance == null)
                    instance = new Logger();
 
               return instance;
          } // get - Instance
      } // property - Instance
} // class - Logger
 
What's wrong with the above code is that we could have a race condition.  View my earlier post on Static Members and Threading Best Practices for ways to fix this problem. 
 
Static Constructors?
 
We can leverage static constructors to load data into our static member variables before the first methods or properties can be called.  The Common Language Runtime locks the object for you while the static constructor is being called, so no additional custom locking needs to happen.  Implicitly, we can do this and behind the scenes, the CLR puts it into the static constructor
 
private static object syncLock = new object();
 
If we need to do something more than just a simple initialization, then we can do this:
 
public sealed class DataAccessHandler
{
     static DataAccessHandler()
     {
          // Do some stuff here
     }
}
 
When to Use Instance Members?
 
From what we talked about above, it should be a little more obvious when you do and do not use static members.  Most operations, unless utility should be instance methods and properties.  Unless the same data needs to be shared among all threads, it's best to use instance for threading purposes as well as good design.  As stated above, you cannot override a static method which defeats a lot of good OO strategies.
 
Follow a Design Pattern
 
It's good to look at design patterns as guides for what should and should not be static.  If you follow the "Gang of Four" book as I always try to, you will notice a couple of patterns that use static well.  Let's cover two of them.
 
Singleton Pattern
 
When you need one and only one instance of an object per AppDomain, the Singleton pattern is the one to use.  For example, I wrote a class that wraps the LocalDataStoreSlot storage on the current Thread so that I can set data and get it and pass easily from class to class.  Here is the pattern followed:
 
public sealed class ThreadCache
{
     private static object syncRoot = new object();
     private static ThreadCache instance;
 
     private ThreadCache()
     {
          // Initialize data
     }
 
     public static ThreadCache Instance
     {
          get
          {
               lock(syncRoot)
               {
                    if(instance == null)
                         instance = new ThreadCache();
                             
                    return instance;
               } // lock - syncRoot
          } // get - Instance
     } // property - Instance
} // class - ThreadCache
 
Concrete Factory
 
The Concrete Factory pattern creates objects without knowing the exact class that it is implementing.  A simple example is below:
 
public abstract class Animal { ... }
 
public class Dog Animal { ... }
public class Cat Animal { ... } 
 
public class AnimalFactory
{
     public static Animal CreateAnimal(string animalType)
     {
          // Switch on animal type on which to create
     }
}
 
The Abstract Factory Pattern cannot use the above code because our factory must have overrideable abstract methods.  See, this comes into play with static versus instance.
 
Static in .NET 2.0
 
In .NET 2.0, the CLR intoduced the capability for classes to be static.  In the past, you had to mark your class as sealed and provide a private constructor.  This cuts down on the lines of code that you have to produce to get the same effect.  This topic is discussed further on the MSDN
 
Conclusion
 
In conclusion, there are times for static members and classes.  The best advice to follow to determine which to use is to follow common design practices.  Static methods are good for when you need the same data available to all threads as well as utilities such as creating a new instance from another type (see DateTime.Parse as an example).  When you do use static member variables, be aware of the multithreaded environment.
 
Posted on Friday, June 9, 2006 11:58 AM .NET , C# | Back to top


Comments on this post: Best Practices - Static or Instance?

# re: Best Practices - Static or Instance?
Requesting Gravatar...
You are correct that static members cannot be overridden, which IMO is their big downfall. However, your example has no threading issues. Ll your variables are local, and new instances created for each call, just as in a normal function. You would only have a threading issue if you used class level variables, and that has nothin to do with being static or not.

The other big pitfall of the static member design is any modifiers for the function must be passed in through parameters, which leads to lots and lots of nested overloads for complex situations. In a non static class, you can set properties which modify the behaviour.
Left by Jason Coyne on Jun 09, 2006 4:35 PM

# re: Best Practices - Static or Instance?
Requesting Gravatar...
You're right. I used the wrong codeblock that I was going to do. I meant to throw in a static shared variable. Thanks for the catch! I just removed the part about threading because that codeblock as written is indeed fine.
Left by Matthew Podwysocki on Jun 11, 2006 7:22 PM

Your comment:
 (will show your gravatar)


Copyright © Matthew Podwysocki | Powered by: GeeksWithBlogs.net