user12426602
user12426602

Reputation:

why Static constructors not called first and i got exception when use declared variable?

From MSDN

A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed once only. It is called automatically before the first instance is created or any static members are referenced

MSDN Link

Now came to my problem:

public static class DateFormat
{
    private static List<string> DateFormats = new List<string>();

    public static string DateSeparator  { get; set; } = "/";

    public static string Current { get; set; } = DateFormats[1]; // error here

    static DateFormat()
    {
        DateFormats.Add("yyyy{0}MM{0}dd HH{1}mm{1}ss");
        DateFormats.Add("yyyy{0}MM{0}dd hh{1}mm{1}ss");
    }
}

As you see above when calling DateFormats[1] error

"The type initializer for 'DateFormat' threw an exception."

Is constructor should calling static constructor first? so that dictionary will filled then any call to variable which use it will be ok.

Upvotes: 0

Views: 138

Answers (2)

Dennis
Dennis

Reputation: 37780

This is how all syntactic sugar is "translated":

static DateFormat()
{
    DateFormats = new List<string>();
    DateSeparator = "/";
    Current = DateFormats[1]; // at this point DateFormats is empty
    DateFormats.Add("yyyy{0}MM{0}dd HH{1}mm{1}ss");
    DateFormats.Add("yyyy{0}MM{0}dd hh{1}mm{1}ss");
}

Don't mix inline initialization and code inside constructor. It's a headache. Especially if class members depends on each other. This is true for instance constructors too.

Upvotes: 1

Matthew Watson
Matthew Watson

Reputation: 109792

This behaviour is documented here: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors

Specifically, this section:

If static field variable initializers are present in the class of the static constructor, they will be executed in the textual order in which they appear in the class declaration immediately prior to the execution of the static constructor.

Since static field variable initializers are indeed present, they will be initialised BEFORE the static constructor, which is why you are seeing that error:

public static string Current { get; set; } = DateFormats[1]; 

will be executed before

static DateFormat()
{
    DateFormats.Add("yyyy{0}MM{0}dd HH{1}mm{1}ss");
    DateFormats.Add("yyyy{0}MM{0}dd hh{1}mm{1}ss");
}

and thus of course, the DateFormats list is still empty at the point that DateFormats[1] is executed.

To solve this, just initialise Current in the static constructor:

public static class DateFormat
{
    static DateFormat()
    {
        DateFormats.Add("yyyy{0}MM{0}dd HH{1}mm{1}ss");
        DateFormats.Add("yyyy{0}MM{0}dd hh{1}mm{1}ss");

        Current = DateFormats[1];
    }

    private static List<string> DateFormats = new List<string>();

    public static string DateSeparator { get; set; } = "/";

    public static string Current { get; set; }
}

Upvotes: 7

Related Questions