Robert Chipperfield

Say hello, static constructor?

Published Friday, August 03, 2007 11:12 AM

When does the static constructor of your .NET class actually get called?

Sounds like it should be pretty obvious really - at least going on the side of "how late can it possibly be called". Most of us are used to the idea that static constructors are called before any other methods on that class are called. I know I hadn't given it too much more thought than that.

According to the MSDN page on static constructors, they will be "...called automatically to initialize the class before the first instance is created or any static members are referenced".

However, what I didn't realise is the implications this had when you start calling static methods on subclasses of your types. Consider the following code:
static class Program
{
static void Main()
{
Sub.SayHello();
Sub.NoOp();
Sub.SayHello();
Console.ReadLine();
}
}

class Super
{
protected static string m_String = "";

static Super()
{
Console.WriteLine("Super..cctor() called");
}

public static void SayHello()
{
Console.WriteLine(m_String);
}
}

class Sub : Super
{
static Sub()
{
Console.WriteLine("Sub..cctor() called");
m_String = "Hello world!";
}

public static void NoOp()
{
}
}
Now, if you run that, I would have expected to see something along the lines of:
Super..cctor() called
Sub..cctor() called
Hello world!
Hello world!
But no! What you actually get is:
Super..cctor() called
<Not set yet>
Sub..cctor() called
Hello world!
In other words, calling a static method on a subclass that is defined on the superclass does not cause the subclass's static constructor to execute! Only when the first member of the subclass is accessed is the static constructor called.

Now, the interesting thing is that if you look at it in Reflector, you'll see that the compiler has actually called Super.SayHello() rather than Sub.SayHello() as in the original source:
private static void Main()
{
Super.SayHello();
Sub.NoOp();
Super.SayHello();
Console.ReadLine();
}
I guess this is a performance win, since the inheritance hierarchy can be traversed at compile-time rather than design-time, but I'm a bit sceptical. Does this really honour the contract that the static constructor will be called before "any static members are referenced"? Let me know what you think!

Comments

 

Thomas Danecker said:

- "I guess this is a performance win, since the inheritance hierarchy can be traversed at compile-time rather than design-time, but I'm a bit sceptical."

There is no inheritance of static methods! It's a feature of C# to be able to use Sub.SayHello instead of Super.SayHello. In sense of IL, Sub.SayHello doesn't exist.

There are quite more impacts of type-initializer than you may think of. According to Jeffrey Richter's book "CLR via C#": At JIT-compile-time, the JIT compiler checks if the type was already initialized. If not, it injects the type initialization directly into the generated native code. So if you are accessing a typ with an type initializer in a tight loop first, you may expect have performance degradations (in Jeffrey's (extreme) example, the loop needed > 300% more time - 7 seconds instead of 2). This behaviour can be relaxed with the BeforeFildInit flag wich is set by the C# compiler if the static fields are inizialized inline and no explicit static constructor is present.
August 6, 2007 1:35 AM
 

RobertChipperfield said:

Hi Thomas,

I know there's no inheritance of static methods, but the fact the syntax (in C# at least) lets you do it is a little misleading in my opinion...

With regards to the performance impact of type initializers, I'd heard about the CLR checks to see whether it'd been run or not, though I didn't realise these were put in or otherwise at JIT time - that's interesting to know.

Cheers,
Rob
August 6, 2007 2:24 AM
You need to sign in to comment on this blog

About RobertChipperfield

I'm a software engineer at Red Gate, where I've worked since September 2006. I've worked on a wide range of products, including SQL Doc, SQL Data Compare, SQL Log Rescue, SQL Multi Script, and ANTS Profiler.

I'm currently working on the new Exchange Server Archiver tool, which should be heading towards release at the start of 2009.

Outside of work, I enjoy amateur radio, electronics, and of course the usual assortment of computer-related technologies, from hardware all the way through to high-level software.


















<August 2007>
SuMoTuWeThFrSa
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678
Go With the Flow
 Knowing enough about the routes that messages take is vital to being an effective Exchange admin,... Read more...

When Email Collaboration Could Have Changed History
 In our mission to make history relevant to the busy IT executive, we speculate how Email might have... Read more...

Bunnikins!
 When an IT manager is selected as a victim of office politics of a large corporate, it is time for him... Read more...

Exchange Database Technologies
 One of the most misunderstood technologies in Exchange Server, regardless of its version, is the... Read more...

Top Tips for Exchange Admins
 Michael Francis hands out imaginary Olympic medals to the winner of the August 'Top Tips for Exchange... Read more...