Damir Arh's Corner
Search
Categories
  Development
 .NET
 Batch
 C++
 SQL
 VB6
 Vista
 Web
 Win32
  Downloads
 Amiga
 Articles
 Presentations
 Sources
 Windows
  Personal
 Education
 Software
 Website
Archives
July, 2008 (1)
June, 2008 (1)
April, 2008 (2)
December, 2007 (1)
November, 2007 (3)
July, 2007 (4)
June, 2007 (1)
May, 2007 (2)
March, 2007 (3)
January, 2007 (1)
December, 2006 (4)
October, 2006 (5)
September, 2006 (3)
August, 2006 (2)
June, 2006 (8)
May, 2006 (5)
April, 2006 (1)
March, 2006 (4)
February, 2006 (3)
January, 2006 (3)
March, 2003 (1)
February, 2002 (1)
January, 2002 (2)
August, 2001 (1)
July, 2001 (1)
February, 2001 (1)
December, 2000 (1)
September, 2000 (1)
July, 2000 (1)
Other Sites
Potepanja v naravi (sl)
Picasa Web Albums (sl)
moj-album.com Gallery (sl)
Bolha.com Auctions (sl)
My Game Space
LinkedIn Public Profile
My GamerTag
Sponsored Links
Administration
Sign In
Friday, February 24, 2006

Static class constructors should never throw an exception (Development | .NET)

I’ve spent a few hours today hunting down a mysterious bug which caused the program to keep reporting failed connections to database server although it was already available for hours. In the end it was a problem of incomplete exception handling but it’s interesting how the problem manifested itself. Let’s look at the following sample code.

using System;
using System.Collections.Generic;
using System.Text;

namespace DamirsCorner.Samples.StaticConstructor
{
   class Program
   {
      static string source;

      class Static
      {
         static Guid problem;

         static Static()
         {
            // will cause an exception if not a valid guid
            problem = new Guid(Program.source);
         }

         public static void Write()
         {
            // will only succeed after successful type initialization
            Console.WriteLine("Success!");
         }
      }

      static void Main(string[] args)
      {
         // setup invalid GUID source value
         source = String.Empty;
         Console.WriteLine("Invalid source value: \"" + source + "\"");
         try
         {
            // type initializer will fail here
            Static.Write();
         }
         catch (Exception e)
         {
            Console.WriteLine("Exception: " + e.Message + "\n\t" + e.InnerException.Message);
         }
         // setup valid GUID source value
         source = Guid.Empty.ToString();
         Console.WriteLine("Valid source value: \"" + source + "\"");
         try
         {
            // type initializer should succeed here
            Static.Write();
         }
         catch (Exception e)
         {
            Console.WriteLine("Exception: " + e.Message + "\n\t" + e.InnerException.Message);
         }
         Console.ReadKey();
      }
   }
}

Ok, there’s no database access here but just imagine that the Guid constructor call is the database access attempt. As you can see, the first call simulates that the server is down while at the second call the server is back up. Keeping that in mind the first call should fail while that second one shouldn't. (For those of you not familiar with static constructors: they get executed before the first (static or instance) property access or method call. As such they take care of type initialization.) Let’s take a look at the program output then.

Invalid source value: ""
Exception: The type initializer for 'Static' threw an exception.
        Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
Valid source value: "00000000-0000-0000-0000-000000000000"
Exception: The type initializer for 'Static' threw an exception.
        Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).

Obviously both calls have failed. Why is that so?

It turns out that the static constructors are executed exactly once. If they throw an exception, it gets wrapped as an InnerException of the TypeInitializationException. Any attempts to use this class afterwards don’t cause the constructor to execute again, but just make it throw the same exception once again. Therefore the method call still reports an invalid GUID value (or in my case failed database connection attempt) although the problem has already been remedied. This makes the class effectively unusable within the AppDomain.

The lesson to be learned: no matter what you’re doing in the static constructor, never allow it to throw an exception unless the problem is indeed fatal and you intend to quit the program immediately. In all other cases provide reasonable defaults and handle changed circumstances elsewhere in the code.

You can find some additional technical details in Chris Brumme’s blog entry.

2/24/2006 12:19:47 AM (Central Europe Standard Time, UTC+01:00)  #  Comments [1]

9/16/2008 9:13:15 PM (Central Europe Standard Time, UTC+01:00)
That was nicely explained. Thanks!
Manas |manas2004AT NOSPAMgmail dot com
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Blog Feeds
RSS 2.0 RSS 2.0
Atom 1.0 ATOM 1.0
Fellow Bloggers
 Andrej Tozon
 Dejan Sarka
 Dusan Zupancic
 Matevz Gacnik
 Miha Markic
Disclaimer
The content of this site are my own personal opinions and do not represent my employer's view in anyway. In addition, my thoughts and opinions often change, and as a weblog is intended to provide a semi-permanent point in time snapshot you should not consider out of date posts to reflect my current thoughts and opinions.

Powered by:
newtelligence dasBlog 1.8.5223.2

© 2008 Damir Arh, M. Sc. Send mail to the author(s)

Microsoft Certified Professional
Currently Reading
Currently Playing
Currently Watching