The static Keyword

April 3, 2008 19:18 by Shay Friedman

We all use the static keyword, but do we really know what the possibilities are?


Prologue

The static keyword is, in general, an instance-less "thing". By "thing", I mean that it can be a variable, a class, a property and more... This definition has different meanings according to which "thing" it's related to.
Let's look into it...


Static Variables

A static variable is the most common use of the static keyword I guess (I don't think there has been a real research to confirm that!).
Marking a variable as static means that:

  • This variable value will be kept through different instances of the class because only one copy of it exists.
  • It cannot be accessed through an instance of a class nor using the this keyword.
  • It will be initialized as soon as its class is initialized or as soon as a method that uses it is called.
  • It will be disposed when the application domain is shutting down.

 

Demo:


public class MyClassWithAStaticVar
{
    public static int x;

    public void Go()
    {
        // this.x = 5; <-- Impossible!
        x = 6; // good!
        MyClassWithAStaticVar.x = 6; // good!
    }
}

public class Demo
{
    public void DoSomething()
    {
        MyClassWithAStaticVar a = new MyClassWithAStaticVar();
        MyClassWithAStaticVar b = new MyClassWithAStaticVar();
        // a.x = 6; <-- Impossible!

        MyClassWithAStaticVar.x = 6;
        // Now both MyClassWithAStaticVar instances (a and b)
        // will get 6 when they ask for x value.           
    }
}


Static Events

Very similar to static variables, static events are not associated with a specific instance of the class. All rules of static variables apply here as well.

Demo:


public class StaticEvents
{
    public static event EventHandler MyStaticEvent;

    public void DoSomething()
    {
        // this.MyStaticEvent(this, EventArgs.Empty); // <-- Impossible!
        MyStaticEvent(this, EventArgs.Empty); // good!
    }
}

public class StaticEventsTester
{
    public void DoSomething()
    {
        StaticEvents s = new StaticEvents();
        // s.MyStaticEvent += StaticEvents_MyStaticEvent; // <-- Impossible!
        StaticEvents.MyStaticEvent += StaticEvents_MyStaticEvent; // good!
    }

    void StaticEvents_MyStaticEvent(object sender, EventArgs e)
    {
        // ...
    }
}


Static Properties/Methods

Defining a property or a method as static can be useful when their logic is not affected by the object state.
Setting a property/method as static means that:

  • It can only access other static objects.
  • It cannot be accessed through an instance of the class nor using the this keyword.

 

Demo:


public class StaticPropsAndMethods
{
    private bool dayOff;

    public static bool IsItMonday
    {
        get
        {
            return (DateTime.Now.DayOfWeek == DayOfWeek.Monday);
        }
        set
        {
            throw new YouAreNotGodException("Monday will come if you want it or not!");
        }
    }

    public static void TakeTheDayOff()
    {
        if (IsItMonday)
        {
            // dayOff = true; // <-- Impossible! dayOff is not static...
            // Now you will have to work on Monday!
        }
    }
}


Static Constructors

Static constructors, as instance constructors, should initialize its class related members. They do have some significant differences though:

  • A static constructor is called between 0 to 1 times during the application domain lifetime.
  • It is triggered when the class is created for the first time or as soon as one of the class' static members is called.
  • It cannot have parameters.
  • It cannot have access modifiers (private, public...)
  • It can access only static members of the class.
  • It cannot be called directly.

These points make static constructors a unique and very important place for various operations - find out when your class is called at the first time, validate class related requirements, execute one-time-only actions, etc.

 

Demo:


public class MyStaticConstructor
{
    // public static MyStaticConstructor(int i) { } // <-- Impossible!

    static MyStaticConstructor() // good!
    {
        // Do some static related
        // operations and initializations
    }
}


Static Classes

Declaring a class as static doesn't give it special abilities, but it is very important for keeping the right design and purpose to the specific class.
Declaring a class as static means that:

  • All of the class members must be declared as static as well (including constructors).
  • An instance of the class cannot be created.
  • The class is sealed, so it cannot be inherited.
  • The class cannot inherit from a base class or an interface.

Going through this list, one can assume that a static class is much the same like a regular class that has static members only. This is almost correct - when a class is set as static, the compiler makes sure that no instances of the class are being created.

Setting a class as static can be very helpful for helper classes. It will help to permanence the class as a helper class with helper methods.

 

Demo:


public static class MyStaticClass
{
    //public void MyMethod()
    //{                            // <--
    //                             // <-- Impossible!
    //}                           // <--

    public static void MyMethod() { } // good!
}

// public static class ChildStaticClass : MyStaticClass {}   // <-- impossible!

public class Demo
{
    public void DoSomething()
    {
        // MyStaticClass c = new MyStaticClass(); <-- Impossible!

        MyStaticClass.MyMethod(); // good!
    }
}


Where static Cannot Be Applied

There are a couple of places where the static keyboard cannot be declared: const and type declarations. This is because these are already static. This means that all of the rules that apply to static variables apply to constant and types within a class.

Demo:


public class NoStatic
{
    // public static const int StaticInt = 1; // <-- Impossible!
    public const int StaticInt = 1; // good!

    //public static enum ABC // <-- Impossible!
    public enum ABC // good!
    {
        A,
        B,
        C
    }

    public void Test()
    {
        // int j = this.StaticInt; // <-- Impossible!
    }
}

public class AnotherClass
{
    public void DoSomething()
    {
        NoStatic s = new NoStatic();
        
        // int j = s.StaticInt; // <-- Impossible!
        int j = NoStatic.StaticInt; // good!

        //int k = (int)s.ABC.C; // <-- Impossible!
        int k = (int)NoStatic.ABC.C; // good!
    }
}


[ThreadStatic]

This is something that is not commonly used and might be helpful sometimes. Use this attribute above static variables in order to make them thread specific.
This means that the variable behaves as static for each thread and not for the whole application.
Notice that using this attribute makes the variable thread-safe.


Epilogue

As I've tried to pass in this post, static is a very powerful keyword BUT it should be used wisely.
One thing to remember - there are no static destructors in .Net. This means that you'll find it hard to release static resources (there are ways, but they are workarounds and workarounds are evil!).

Demo - how NOTto use static classes:


public static class AbusedStaticClass
{
    // Please do NOT code like that! Pleaseeeeeeee!
    public static StreamWriter MyFile;                                                                           
    static AbusedStaticClass()                                       
    {
        MyFile = new StreamWriter(@"DontDoThis.txt");   
    }                                                   
}   


This was a long post! Kudos to those who made it to the end! :)
I hope you've been enlightened,
All the best,
Shay.

kick it on DotNetKicks.com  


Comments

April 4. 2008 04:35

Bart Czernicki

// public static const int StaticInt = 1; // <-- Impossible!
public static int StaticInt = 1; // good!

I think u meant to show the const here...so this line:
public static int StaticInt = 1; // good!

should be defined:
public const int StaticInt = 1;

Bart Czernicki

April 4. 2008 06:30

Shay Friedman

Thanks for the comment Bart, I've fixed the confusing statement.

Shay Friedman

April 6. 2008 08:27

pingback

Pingback from rtipton.wordpress.com

Weekly Link Post 36 « Rhonda Tipton’s WebLog

rtipton.wordpress.com

April 6. 2008 18:07

pingback

Pingback from blog.cwa.me.uk

Reflective Perspective - Chris Alcock » The Morning Brew #67

blog.cwa.me.uk

Add comment


(Will show your Gravatar icon)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

November 19. 2008 18:19