0

What exactly causes the execution of a static constructor in C#? I'm testing with .NET 4.0 both in Windows and via Mono on Linux and I see the same behavior.

I always thought the first time that there was a reference to the class that it would trigger the code to run but with this demo, it appears it's more related to the first time there's a request to execute something on the class.

Can somebody please explain this a little more clearly? Also, other than the fact that lambda expressions haven't always been around, does this behavior change at all with different versions of .NET?

Code:

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        Console.WriteLine("1. Main Started!");
        Expression<Func<bool>> func = (() => Foo.ReturnFalse());
        Console.WriteLine("2. Func func has been created.");
        Console.WriteLine("3. Func func returns: " + func.Compile().Invoke());
    }
}

public static class Foo
{
    static Foo()
    {
        Console.WriteLine("?. Initializing Foo");
    }

    public static bool ReturnFalse()
    {
        return false;
    }
}

Output:

1. Main Started!
2. Func func has been created.
?. Initializing Foo
3. Func func returns: False

What I expected:

1. Main Started!
?. Initializing Foo
2. Func func has been created.
3. Func func returns: False
Jaxidian
  • 13,081
  • 8
  • 83
  • 125
  • 1
    the best answer is "its complicated"; see also http://ericlippert.com/2013/02/06/static-constructors-part-one/ and subsequent posts. – Michael Edenfield Dec 19 '14 at 19:07
  • That duplicate being marked does not answer a single one of my questions. :-( – Jaxidian Dec 19 '14 at 19:07
  • @Jaxidian It does, and your own explanation matches the output you get, not the output you expected, too. `Expression> func = (() => Foo.ReturnFalse());` does not actually use anything in `Foo` just yet. It's not exactly like, but still similar to, `private bool MyFunc() { return Foo.ReturnFalse(); }`, and then `Func func = MyFunc;`, which does not concern itself with `MyFunc`'s body, so does not do anything with `Foo`'s static constructor. –  Dec 19 '14 at 19:10
  • Microsoft's documentation states that the static constructor is called at most one time, before any instance constructor is invoked or member is accessed. Also: The user has no control on when the static constructor is executed in the program. No other clues from MSDN. – Bruce Dec 19 '14 at 19:11
  • So using .NET to dynamically build a body that references a class does not constitute using that class? What about other obscure scenarios like attempting a safe cast from an object to a class? `var x = y as Foo;` (spoiler, same order). Are there any other obscure scenarios like this to be aware of? – Jaxidian Dec 19 '14 at 19:15
  • @Jaxidian Creating an anonymous function that uses a class' member does not consitute accessing that class' member, much in the same way that the statement `Action nre = () => ((object)null).ToString();` does not cause a `NullReferenceException`.Attempting a safe cast does not match either of the criteria cited in the spec for invoking a static constructor, but you are more than welcome to try it. – JLRishe Dec 19 '14 at 19:23
  • @Jaxidian you should read the series of articles from Eric Lippert I included in my first comment, as they are about exactly the kind of thing you're asking: what odd scenarios can result in my static constructor not running. – Michael Edenfield Dec 19 '14 at 20:35
  • @MichaelEdenfield I have now and they are proving valuable. Thank you for that link! – Jaxidian Dec 19 '14 at 21:57

0 Answers0