I have the following piece of codes.
class Program
{
static void Main(string[] args)
{
Enterprise.Initialize("Awesome Company");
// Assertion failed when constructor of 'Reg' class is disabled.
Debug.Assert(Reg.Root == @"Software\Awesome Company");
}
}
public static class Enterprise
{
// Static Properties.
public static string Company
{
get;
private set;
}
// Static Methods.
public static void Initialize(string company)
{
Company = company;
}
}
public class Reg
{
public static string Root = $@"Software\{Enterprise.Company}";
// ctor.
static Reg()
{
// Assertion failed when this constructor is disabled.
}
}
When executed, the assertion passed. However, the assertion failed when the constructor for Reg
class is disabled. On a closer look, I've found that the implicit constructor of Reg
class is called before Main()
. If the constructor of Reg
class is explicitly defined, it will be called after Main()
.
Why such discrepancy between implicit and explicit constructor?
A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed only once. It is called automatically before the first instance is created or any static members are referenced.
Static constructors are used to initialize the static members of the class and are implicitly called before the creation of the first instance of the class. Non-static constructors are used to initialize the non-static members of the class.
In C# terms, the base constructor is executed first.
A class or struct can only have one static constructor. Static constructors cannot be inherited or overloaded.
This is a quirk of chained static class initialization.
From the ECMA C# Specifications
15.5.6.2 Static field initialization
The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration (§15.5.6.1). Within a partial class, the meaning of "textual order" is specified by §15.5.6.1. If a static constructor (§15.12) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.
Take special note of the last part, this is your problem, if you don't have a static constructor you have no control over when the field is initialized. In your test case they are being initialized before you call Enterprise.Initialize
In short, you shouldn't be relying on these rules, it's easy to make mistakes and is likely to cause weird issues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With