zoukankan      html  css  js  c++  java
  • beforefieldinit释义

    首先让我们认识什么是,当字段被标记为beforefieldinit类型时,该字段初始化可以发生在任何时候任何字段被引用之前。这句话听起了有点别扭,接下来让我们通过具体的例子介绍。

    /// <summary>
    /// Defines a test class.
    /// </summary>
    class Test
    {
        public static string x = EchoAndReturn("In type initializer");
    
        public static string EchoAndReturn(string s)
        {
            Console.WriteLine(s);
            return s;
        }
    }

    上面我们定义了一个包含静态字段和方法的类Test,但要注意我们并没有定义静态的构造函数。 

                                                                                                         singleton2

    图3 Test类的IL代码 

    class Test
    {
        public static string x = EchoAndReturn("In type initializer");
    
        // Defines a parameterless constructor.
        static Test()
        {
        }
    
        public static string EchoAndReturn(string s)
        {
            Console.WriteLine(s);
            return s;
        }
    }
    View Code

         上面我们给Test类添加一个静态的构造函数。 

      singleton3

                                    图4 Test类的IL代码 

           通过上面Test类的IL代码的区别我们发现,当Test类包含静态字段,而且没有定义静态的构造函数时,该类会被标记为beforefieldinit。

           现在也许有人会问:“被标记为beforefieldinit和没有标记的有什么区别呢”?OK现在让我们通过下面的具体例子看一下它们的区别吧!

    class Test
    {
        public static string x = EchoAndReturn("In type initializer");
    
        static Test()
        {
        }
    
        public static string EchoAndReturn(string s)
        {
            Console.WriteLine(s);
            return s;
        }
    }
    
    class Driver
    {
        public static void Main()
        {
            Console.WriteLine("Starting Main");
            // Invoke a static method on Test
            Test.EchoAndReturn("Echo!");
            Console.WriteLine("After echo");
            Console.ReadLine();
    
            // The output result:
            // Starting Main
            // In type initializer
            // Echo!
            // After echo            
        }
    }
    View Code

          我相信大家都可以得到答案,如果在调用EchoAndReturn()方法之前,需要完成静态成员的初始化,所以最终的输出结果如下: 

    singleton4

               图5输出结果

        接着我们在Main()方法中添加string y = Test.x,如下: 

    public static void Main()
    {
        Console.WriteLine("Starting Main");
        // Invoke a static method on Test
        Test.EchoAndReturn("Echo!");
        Console.WriteLine("After echo");
    
        //Reference a static field in Test
        string y = Test.x;
        //Use the value just to avoid compiler cleverness
        if (y != null)
        {
            Console.WriteLine("After field access");
        }
        Console.ReadKey();
    
        // The output result:
        // In type initializer
        // Starting Main
        // Echo!
        // After echo
        // After field access
    
    }
    View Code

    singleton5

    图6 输出结果

            通过上面的输出结果,大家可以发现静态字段的初始化跑到了静态方法调用之前,Wo难以想象啊!

            最后我们在Test类中添加一个静态构造函数如下:

    class Test
    {
        public static string x = EchoAndReturn("In type initializer");
    
        static Test()
        {
        }
    
        public static string EchoAndReturn(string s)
        {
            Console.WriteLine(s);
            return s;
        }
    }
    View Code

     singleton6

           图7 输出结果 

           理论上,type initializer应该发生在”Starting Main”之后和”Echo!”之前”,但这里却出现了不唯一的结果,只有当Test类包含静态构造函数时,才能确保type initializer的初始化发生在”Starting Main”之后和”Echo!”之前”。

    所以说要确保type initializer发生在被字段引用时,我们应该给该类添加静态构造函数。

  • 相关阅读:
    蓄水池抽样(Reservoir Sampling )
    动态申请一个二维数组
    最大子段和问题分析和总结
    正则表达式语法
    正则表达式介绍
    小刘同学的第七十六篇博文
    小刘同学的第七十五篇博文
    小刘同学的第七十四篇博文
    小刘同学的第七十三篇博文
    小刘同学的第七十二篇博文
  • 原文地址:https://www.cnblogs.com/HappyEDay/p/5416731.html
Copyright © 2011-2022 走看看