Question

I have a class as follows :

static class Configuration
    {
        private static AppSettingsSection _appSettingsLogsSection;
        static Configuration()
        {
            var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            _appSettingsLogsSection = config.GetSectionGroup("Logs").Sections["appSettings"] as AppSettingsSection;
        }

        public static int LogSendIntervalMinutes = Convert.ToInt32(_appSettingsLogsSection.Settings["LogSendIntervalMinutes"]);

    }

Now, as per my understanding, the static constructor should be called before the first reference to any static member is made. But surprisingly, it is not behaving like that. When I reference LogSendIntervalMinutes from Main class, instead of triggering the static constructor, call goes straight to the static field resulting in a NullReferenceException.

Am I doing something wrong here and is my understanding correct?

Was it helpful?

Solution 2

From MSDN:

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.

So try to move the initialization to before the static constructor, or include the association in the static constructor itself.

And even though, you are trying something impossible, since the static field uses a variable declared inside the static constructor.

Try this:

private static AppSettingsSection _appSettingsLogsSection;
public static int LogSendIntervalMinutes;

static Configuration()
{
    var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    _appSettingsLogsSection = config.GetSectionGroup("Logs").Sections["appSettings"] as AppSettingsSection;

    LogSendIntervalMinutes = Convert.ToInt32(_appSettingsLogsSection.Settings["LogSendIntervalMinutes"]);        }
}

OTHER TIPS

Static fields are always initialized before static constructor is called. You should initialize LogSendIntervalMinutes in static constructor as well. I'd suggest you even make it a property:

static class Configuration
{
    private static AppSettingsSection _appSettingsLogsSection;
    public static int LogSendIntervalMinutes { get; private set; }
    static Configuration()
    {
        var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        _appSettingsLogsSection = config.GetSectionGroup("Logs").Sections["appSettings"] as AppSettingsSection;
        LogSendIntervalMinutes = Convert.ToInt32(_appSettingsLogsSection.Settings["LogSendIntervalMinutes"]);
    }
}

Quote from C# language specification (I added the emphasis):

10.4.5.1 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. If a static constructor (Section 10.11) 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.

Look at the compile code using ILSpy or Reflector you will find your answer.

Actually field initializers are automatically moved inside constructor before your actual code of constructor. (static moves to static one and instance to instance contructor).

Decompile code of your class using reflector:

enter image description here

and actual class structure look like this:

enter image description here

Also you can see the optimization done by compiler to integrate two separate lines in constructor to single line to initialize _appSettingsLogsSection.

Initializations of static fields are actually part of the type constructor and are executed before the custom type constructor is called. Thus, if LogSendIntervalMinutes was an instance field, there would be no problem, but as it is static, its initialization is executed before your static constructor. You just need to put the initialization of LogSendIntervalMinutes inside the your type constructor.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top