How can I run a static constructor?

前端 未结 10 1333
面向向阳花
面向向阳花 2020-12-08 02:15

I\'d like to execute the static constructor of a class (i.e. I want to \"load\" the class) without creating an instance. How do I do that?

Bonus question: Are there

相关标签:
10条回答
  • 2020-12-08 02:31

    The other answers are excellent, but if you need to force a class constructor to run without having a reference to the type (i.e. reflection), you can use RunClassConstructor:

    Type type = ...;
    System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);
    
    0 讨论(0)
  • 2020-12-08 02:32

    Extending Fábio's observations, the following short and complete test program exposes the JIT-sensitive details of TypeAttributes.BeforeFieldInit behavior, comparing .NET 3.5 to the latest version (as of late 2017) .NET 4.7.1, and also demonstrates the potential hazards for build type variations within each version itself.[1]

    using System;
    using System.Diagnostics;
    
    class MyClass
    {
        public static Object _field = Program.init();
    
        public static void TouchMe() { }
    };
    
    class Program
    {
        static String methodcall, fieldinit;
    
        public static Object init() { return fieldinit = "fieldinit"; }
    
        static void Main(String[] args)
        {
            if (args.Length != 0)
            {
                methodcall = "TouchMe";
                MyClass.TouchMe();
            }
            Console.WriteLine("{0,18}  {1,7}  {2}", clrver(), methodcall, fieldinit);
        }
    };
    

    Below is the console output from running this program in all combinations of { x86, x64 } and { Debug, Release }. I manually added a delta symbol Δ (not emitted by the program) to highlight the differences between the two .NET versions.

    .NET 2.0/3.5

    2.0.50727.8825 x86 Debug
    2.0.50727.8825 x86 Debug TouchMe fieldinit
    2.0.50727.8825 x86 Release fieldinit
    2.0.50727.8825 x86 Release TouchMe fieldinit
    2.0.50727.8825 x64 Debug
    2.0.50727.8825 x64 Debug TouchMe fieldinit
    2.0.50727.8825 x64 Release
    2.0.50727.8825 x64 Release TouchMe fieldinit

    .NET 4.7.1

    4.7.2556.0 x86 Debug
    4.7.2556.0 x86 Debug TouchMe fieldinit
    4.7.2556.0 x86 Release Δ
    4.7.2556.0 x86 Release TouchMe Δ
    4.7.2556.0 x64 Debug
    4.7.2556.0 x64 Debug TouchMe fieldinit
    4.7.2556.0 x64 Release
    4.7.2556.0 x64 Release TouchMe Δ

    As noted in the intro, perhaps more interesting than the version 2.0/3.5 versus 4.7 deltas are the differences within the current .NET version, since they show that, although the field-initialization behavior nowadays is more consistent between x86 and x64 than it used to be, it's still possible to experience a significant difference in runtime field initialization behavior between your Debug and Release builds today.

    The semantics will depend on whether you happen to call a disjoint or seemingly unrelated static method on the class or not, so if doing so introduces a bug for your overall design, it is likely to be quite mysterious and difficult to track down.


    Notes
    1. The above program uses the following utility function to display the current CLR version:

    static String clrver()
    {
        var s = typeof(Uri).Assembly.Location;
        return FileVersionInfo.GetVersionInfo(s).ProductVersion.PadRight(14) +
            (IntPtr.Size == 4 ? " x86 " : " x64 ") +
    #if DEBUG
            "Debug  ";
    #else
            "Release";
    #endif
    }
    
    0 讨论(0)
  • 2020-12-08 02:33

    There is no need to do this, the whole point of a static constructor is that it runs once when the class is first initialised at first access. If you want to run something on demand, then consider adding your initialisation code into a public method that is called by the constructor. You can then call this method whenever you like. But I'm not sure why you would want to do this?

    0 讨论(0)
  • 2020-12-08 02:39

    The static constructor runs automatically the first time you access the class. There is no need (or capability) to 'run' it yourself.

    0 讨论(0)
  • 2020-12-08 02:50

    Static constructors are NOT always called when accessing a static method!

    I noticed that if you call a static method in a base class, the static constructor of the super class is NOT called. This unexpected behavior has bitten many times.

    0 讨论(0)
  • 2020-12-08 02:51

    The cctor (static constructor) will be called whenever one of the following occurs;

    1. You create an instance of the class
    2. Any static member is accessed
    3. Any time before that, if BeforeFieldInit is set

    If you want to explicitly invoke the cctor, assuming you have other static members, just invoke/access them.

    If you are not doing anything very interesting in your cctor, the compiler may decide to mark it BeforeFieldInit, which will allow the CLR the option to execute the cctor early. This is explained in more detail here: http://blogs.msdn.com/davidnotario/archive/2005/02/08/369593.aspx

    0 讨论(0)
提交回复
热议问题