Static Constructor throws the same exception again and again

Here’s a little gotcha I ran into today – if you have code in a class’s static constructor that throws an exception, we will get a TypeInitializationException with the original exception as the InnerException – so far, nothing new.

However, if we keep on calling methods on that object, we’ll keep receiving TypeInitializationExceptions. If it cannot be initialized, it cannot be called. Every time we try, we’ll receive the exact same exception. However, the static ctor will not be called again. What appears to happen is that the CLR caches the TypeInitializationException object itself, InnerException included, and rethrows it whenever the type is called.

What are the ramifications? Well, we received an OutOfMemoryException in our static ctor, but the outer exception was caught and tried again. So we got an OutOfMemoryException again, even though the memory problem was behind us, which sent us down the wrong track of looking for persistent memory problems. Theoretically, it could also be a leak – the inner exception holding some sort of reference that is never released, but that’s an edge case.

Here’s some code to illustrate the problem. The output clearly shows that while we wait a second between calls, the inner exception contains the time of the original exception, not any subsequent calls. Debugging also shows that the static ctor is called only once.

   1:  class Program
   2:  {
   3:      static void Main(string[] args)
   4:      {
   6:          for (int i = 0; i < 5; i++)
   7:          {
   8:              try
   9:              {
  10:                  Thread.Sleep(1000);
  11:                  StaticClass.Method();
  13:              }
  14:              catch (Exception ex)
  15:              {
  16:                  Console.WriteLine(ex.InnerException.Message);
  17:              }
  18:          }
  20:          Console.ReadLine();
  21:      }
  22:  }
  24:  static class StaticClass
  25:  {
  26:      static StaticClass()
  27:      {
  28:          throw new Exception("Exception thrown at " + DateTime.Now.ToString());
  29:      }
  31:      public static void Method()
  32:      { }
  34:  }

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.