8

I stumbled upon a problem where i need an instance of the class inside its static constructor. I believed it was not possible to do it so i tried the following:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Foo.someString);
        Console.ReadLine();
    }
}

class Foo
{
    public static readonly string someString;

    static Foo()
    {
        someString = new Foo().CreateString();
    }

    private string CreateString()
    {
        return "some text";
    }
}

To my surprise, it works - the output is "some text". I believed the static constructor must run and complete before instances of the class can be created. This answer shows that this is not necessarily the case. Does this mean that static and instance constructors are independent of each other? And finally, is it safe to do this (create instances in static constructor)?

p.s. Let's ignore the fact that this can be avoided by using a different approach.

Community
  • 1
  • 1
loodakrawa
  • 1,468
  • 14
  • 28

3 Answers3

5

All that the specification says is that the static constructor will be called before any instance of the class is created. But it doesn't state anything about the fact that this constructor must finish:

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.

You could perfectly fine create instances of the class inside the static constructor and this is safe.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • depending on the difinition of safe, the location of the instantiation and the usage of the created instance – Rune FS Feb 20 '12 at 09:55
  • @Rune FS - safe to do a similar thing as in the example - initialize a static member variable – loodakrawa Feb 20 '12 at 09:59
  • Do be careful when static constructors are dependent on other static constructors. Try not to get a circular dependency, because that can cause you to access members and create instances of the class before the static initializer has completed running. The Framework will not warn you for this (i.e., no exceptions or deadlocks). – Ruben Feb 20 '12 at 10:10
  • @Ruben - I am aware of circular dependency problems. However, i have a clean situation in this case - it is similar to the simplified example i have given. But thanx for the warning. – loodakrawa Feb 20 '12 at 10:14
  • @loodakrawa that can't be answered generally because it depends on the implementaiton of CreateString. You use a constant which will be safe. If the implementation relies on other static parts of the class then the order in which you initialize in the constructor becomes an issue. If you do nothing else than instantiate and call an instance method or do this as the very last thing then odds are that it's safe but also so much of an oddity that it could be (deliberately) neglected in a future version of the CLR/C# if it stood in the way of something more important – Rune FS Feb 20 '12 at 10:30
0

Static constructor called automatically before the first instance is created or any static members are referenced any static fields are referenced. Hence when your application ran and you accessed Foo, the static constructor was executed and your string was initialized.

Is it safe ? : As such there is no harm in doing this. It is just they are executed only once.

For information on this read Static Classes and Static Class Members on MSDN

Amar Palsapure
  • 9,590
  • 1
  • 27
  • 46
  • First of all static constructors are call at the first access to the type (members), not when the assembly holding the type is loaded. Secondly when the static constructor is called above an instance is created which is what OP is asking about being safe or not. So even if the statement about when the constructor is called it does change that OP is instantiating at that particular time – Rune FS Feb 20 '12 at 09:59
  • Don't know who's the downvoter, but your statement "Static constructor is called when application is loaded in the memory." is not true. – Mentoliptus Feb 20 '12 at 09:59
  • I didn't downvote, but I guess it's because of the phrase "when application is loaded in the memory". That's not true: it's run just in time, just before you start using the class (exact semantics differ per framework version). If you don't use the class in any way, the static initializer is never called. Sometimes it's not even called even when you *are* using a class (e.g., when you're calling a static method on a class that's not accessing the static fields of the class; again the exact behavior differs per framework version). – Ruben Feb 20 '12 at 10:05
  • @Ruben The above information which I got is from MSDN. http://msdn.microsoft.com/en-us/library/k9x6w0hc(v=vs.80).aspx. – Amar Palsapure Feb 20 '12 at 10:08
  • I'd dv'ed and posted the comment immediately after, that's the least I could do. However they are not published immediately. I've removed the dv. since the statement has been corrected – Rune FS Feb 20 '12 at 10:08
  • @AmarPalsapure: Sorry, my typing is not as fast as yours; I'll update my comment. However, the statement in MSDN is slightly misleading. With "before ... any static members are referenced" methods and properties are not counted, it's really "before ... any static *fields* are referenced". See [Type initialization changes in .NET 4.0](http://msmvps.com/blogs/jon_skeet/archive/2010/01/26/type-initialization-changes-in-net-4-0.aspx). – Ruben Feb 20 '12 at 10:17
  • @Ruben: +1 interesting stuff. Will need to update my answer again. :) – Amar Palsapure Feb 20 '12 at 10:23
0

It is safe as it will be called only once.

Ebad Masood
  • 2,389
  • 28
  • 46