0

I have a problem with static initialization when I follow a Singleton approach and I don't understand what is going on here. Target framework is 4.5. This is a brand new project. Did not modify any settings.

Here I made a sample of the offending code, the expected result is that "Static Value" should appear on the console. However, nothing appears. Debugging in fact shows that at the time of Console.Write the static variable Static_Value is null.

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Test MyClass = Test.Instance;

            Console.ReadKey();
        }
    }

    class Test
    {
        public static Test _instance = new Test();

        public static Test Instance
        {
            get { return _instance; }
        }

        public static readonly string Static_Value = "Static Value";

        static Test()
        {

        }

        private Test()
        {
            Console.Write(Static_Value + Environment.NewLine);
        }
    }
}

if I drop the singleton approach instead, it works.

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Test MyClass = new Test();

            Console.ReadKey();
        }
    }

    class Test
    {
        public static Test _instance = new Test();

        public static Test Instance
        {
            get { return _instance; }
        }

        public static readonly string Static_Value = "Static Value";

        public Test()
        {
            Console.Write(Static_Value + Environment.NewLine);
        }
    }
}

I am definitely puzzled on what is going on here. Aren't static variables initialized the first time they are accessed? Because it doesnt't seem to be happening....

Can anyone shed some light here?

EDIT:

following René Vogt hint I modified my code according to the standard, and it now works. As all static initializers side effect are accounted when the static constructor runs, I moved the initialization of the _instance to the static constructor, which will anyway run before the getter of Instance runs.

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Test MyClass = Test.Instance;

            Console.ReadKey();
        }
    }

    class Test
    {
        private static Test _instance;

        public static Test Instance
        {
            get { return _instance; }
        }

        public static readonly string Static_Value = "Static Value";

        static Test()
        {
            _instance = new Test();
        }

        private Test()
        {
            Console.Write(Static_Value + Environment.NewLine);
        }
    }
}
user1464603
  • 437
  • 4
  • 8
  • 1
    I guess the problem is that you call the _instance_ constructor `Test()` _while_ the _static_ construction is running. So `_instance_` is initialized first, calling `Test()` before `Static_Value` is initiaized. – René Vogt Jun 12 '17 at 12:00
  • It's all about the initialization order. See the linked question for details. – dymanoid Jun 12 '17 at 12:01
  • I recommend reading John Skeet's blog post about singletons http://csharpindepth.com/Articles/General/Singleton.aspx – juharr Jun 12 '17 at 12:02
  • 1
    Put the declaration of `Static_Value` before the declaration of `_instance`, et voila. (No, this isn't something you want to rely on in general.) "If a class contains any static fields with initializers, those initializers are executed *in textual order* immediately prior to executing the static constructor." – Jeroen Mostert Jun 12 '17 at 12:03
  • @bassfader I am. When I assign from property Instance i run it's getter, it runs the private Test() constructor thus calling Console.Write. – user1464603 Jun 12 '17 at 12:04
  • @René Vogt ok. Thank you for pointing the answer. I have been searching on google but I got flooded with results when searching for anything related to C# "static" initialization. – user1464603 Jun 12 '17 at 12:13
  • 4
    In general, if you're doing anything non-trivial with static initializers, move everything to the static constructor and don't rely on the textual inline initialization. Even more generally, singletons generally suck -- avoid them in favor of injected instances. When you simply can't do without one, the [`Lazy`](https://msdn.microsoft.com/en-us/library/dd642331) type offers a way to initialize them in a way that's more temporally predictable than with a static initializer -- if a static initializer fails, you get a `TypeInitializationException` that might occur in hard to predict places. – Jeroen Mostert Jun 12 '17 at 12:14

0 Answers0