C# · CodeProject · Dotnet

Static in generics

Dear Reader,

Although this topic is quite common, but still i see here and there folks getting confused about the behavior of having a static members in the generic type.

Today i saw another question on stackoverflow about the same. So i thought i shall write a small blog post about the same.

Normally we know that static members are unique for a type no matter how many instance you create of that type. But this concept behaves a bit differently in generics. If you have read the C# spec, then you would have figured out by now. It states some thing like this “For every open type T, the type having static members maintains the common/unique value”.

Let me show you a sample code for explanation:

public class Base
    {
        public static string str = null;

        static Base()
        {
            str = "hello";

            Console.WriteLine("Ctor cald");
        }
    }

As you can see in the above code, the static member by virtue of its nature stays common/unique for this type Base no matter how many derived/base instances are created right. Yep.

But as soon as you introduce generics to this code, things starts to behaves a bit differently. As already stated above, for each open type T (in below code) the base type holds a common static members in it.

Lemme show you a sample code for the same:

public class Base < T >
    {
        public static string str = null;

        static Base()
        {
            str = "hello";

            Console.WriteLine("Ctor cald");
        }
    }

    public class Derived1 < T > : Base < T > { }
    public class Derived2 < T > : Base < T > { }

    public class Program
    {
         public static void Main()
        {
            Derived1 < int > derv = new Derived1 < int >();
            Derived2 < double > derv2 = new Derived2() < double >;
            Derived2 < double > derv3 = new Derived2() < double >;

            Console.ReadKey();
        }
    }

So how many times the static ctor in the above code would be called? 3? No, wrong. In this case, its only 2 times. Because for every open type T you pass (in this case int and double types in main method) the base types static members are maintained unique for that open type T.

If you supposedly run FxCop on your generic type code having static members, you would get this warning. So be careful in using static in generics.

Hope it helps. Thanks for reading.

Your comments/votes are always appreciated πŸ™‚

Happy coding.

Advertisements

6 thoughts on “Static in generics

  1. It might be more interesting to compare Derived1 and Derived2 instead of two instances of Derived2. It’s not that surprising that the static constructor is run only once in that case.

    It’s worth pointing out that this feature of the language/runtime can be put to good use. If you want to create a static cache of objects of any type indexed by a string, you can have an ObjectCache type that has a static Dictionary. Then you will be creating a new Dictionary object for each T that is used at runtime.

    Also, note that in Java this is not the case due to type erasure. Since generic types do not exist at runtime (they are purely a compile-time construct) static members on generic classes are only initialized once, and there is really only once instance of them.

    1. It might be more interesting to compare Derived1 and Derived2 instead of two instances of Derived2. It’s not that surprising that the static constructor is run only once in that case.
      Are you talking about this code below?

       public class Base < T  
      {
              public static string str;
      
              static Base()
              {
                  str = "hello";
                  System.Console.WriteLine("Static ctor cald");
              }
          }
      
          class Derived1 < T : Base  T
          { }
      
          class Derived2 < T : Base  < T
          { }
      
         class Program 
          {
              public static void Main(string[] args)
              {
                  Derived1 <int der = new Derived1<int ();
                  Derived2 <int der1 = new Derived2<int ();
      
                  Console.ReadKey();
              }     
      

      If so, i thought this code might create a lil confusion. Hence i did showed the other one. But yes this also a good example. Thanks πŸ™‚

      It’s worth pointing out that this feature of the language/runtime can be put to good use. If you want to create a static cache of objects of any type indexed by a string, you can have an ObjectCache type that has a static Dictionary. Then you will be creating a new Dictionary object for each T that is used at runtime.

      Btw, would you mind showing an real world example where this design challenge is put into effect? Perhaps a code plz?

      Note: In the code above, the closing angle braces are purposefully left because of wordpess issues.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s