What is a static constructor, and when does it run?
Quick Answer
A static constructor initialises static members and runs once per type, automatically, just before the first time the type is used (first instance created or first static member accessed). The runtime guarantees it's thread-safe and runs exactly once.
A static constructor runs once for the whole type, the first time you touch that type — create an instance or read a static field. You don't call it; the runtime does, and it guarantees it happens exactly once even with multiple threads racing. It's where you'd set up static state that needs logic beyond a simple initializer. Two things to watch: if it throws, you get a TypeInitializationException and that type is dead for the rest of the process, and adding one changes the beforefieldinit behaviour so initialization timing becomes stricter.
- No access modifier, no parameters; you can't call it directly.
- If it throws, the exception is wrapped in
TypeInitializationExceptionand the type is unusable for the rest of the process. - Having any static constructor removes the
beforefieldinitflag, making initialization more precisely timed but slightly less eager — occasionally a micro-perf consideration. - For expensive lazily-created singletons,
Lazy<T>is usually clearer than leaning on static-ctor timing.