Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit static constructor called before Main()

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?

like image 396
Noctis Tong Avatar asked Sep 03 '20 07:09

Noctis Tong


People also ask

Why static constructor is called first?

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.

Which constructor will be called first static or normal constructor?

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.

Which constructor is called first in C#?

In C# terms, the base constructor is executed first.

How many static constructors can be declared in a class?

A class or struct can only have one static constructor. Static constructors cannot be inherited or overloaded.


1 Answers

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.

like image 101
TheGeneral Avatar answered Oct 13 '22 00:10

TheGeneral