zoukankan      html  css  js  c++  java
  • 6 CLR静态构造器

    CLR保证一个类型构造器在每个AppDomain中只执行一次,而且这种执行是线程安全的。

     

    作用:

    就是初始化静态成员

    比如有几个静态成员需要初始化
    那你把初始化代码放到哪呢?

    放到普通构造函数里,那肯定不行。因为静态成员没有创建实例就要可用。

    专门建一个static public方法来初始化?这样用起来非常不方便,你需要在“第一次”使用静态成员前先调用这个方法。
    如果你在使用静态成员前忘了调用该方法,会导致错误。
    如果重复调用,又是冗繁操作。

    所以静态构造函数就派上用场了。
    它会在你第一次调用静态成员(或创建实例)的时候自动被调用

    解析:

    静态构造器函数是实现对一个类进行初始化的方法成员,它一般用于对静态数据的初始化。静态构造函数不能有参数,不能有修饰符而且不能被调用,当类被加载时,类的静态构造器自动被调用。

           在一个程序的执行过程中,静态构造器最多只执行一次。

           静态构造器在类的静态成员初始化之后执行,或者讲编译器会将静态成员初始化语句转化成赋值语句放在静态构造器执行的最开始。

           静态构造器在任何类的静态成员被引用之前执行。

           静态构造器在任何类的实例变量被分配之前执行。

    静态构造器最主要的作用是对类的静态成员进行初始化。

    namespace 静态构造器
        {
            class A
            {
                public static int i = 100;
                static A()                         //静态构造器能不能带参数,不能有修饰符,默认private
                {
                    Console.WriteLine("我是类A的静态构造器");
                }
    
    
                public A()
                {
                    Console.WriteLine("我是类A的无参构造器");
                }
            }
    
            //编译之后等价于
            //class A
            //{
            //    public static int i ;
            //    static A()                         //静态构造器能不能带参数,不能有修饰符,默认private
            //    {
            //        i = 100;
            //        Console.WriteLine("我是类A的静态构造器");
            //    }
    
    
            //    public A()
            //    {
            //        Console.WriteLine("我是类A的无参构造器");
            //    }
            //}
    
    
            class Program
            {
                static void Main(string[] args)
                {
                    Console.WriteLine(A.i);//当类被加载时,类的静态构造函数自动被调用,静态构造器是在a被使用前加载的
    
                    // A a = new A();     //静态构造器最多只执行一次
    
                    Console.ReadKey();
                }
            }
        }

    最近看书,看到静态构造函数的时候,发现其不能从程序中显示调用,而通常静态构造函数初始化类的静态字段,这样的话,为何不直接在静态字段定义的时候直接为其赋值呢?

    直接赋值的结果就是它们会被放到静态构造函数中执行.

    和一般的构造函数类似的呀,赋值只是构造函数的一个功能。有时候,你需要在静态构造函数中写一些逻辑,或是执比一些代码,比如工厂模式中很多的,要读取配置文件,然后把根据配置的文件初使化一些常用的对象,比如单例模式中的唯一对象,或者spring中的session什么的。反正一句话是,有些逻辑也要放在构造函数中,静态的也是。

    先看代码:

    1.包含静态字段的调用

    1. class Program  
    2. {  
    3.     static void Main(string[] args)  
    4.     {  
    5.         Console.WriteLine("EntryPoint");  
    6.         Console.WriteLine(StaticClass.staticMem);  
    7.         StaticClass.ShowStaticStr("Call Static Method");  
    8.         Console.Read();  
    9.     }  
    10.   
    11.     class StaticClass  
    12.     {  
    13.         public static string staticMem = ShowStaticStr ("Static Member");  
    14.         public static string ShowStaticStr(string message)  
    15.         {  
    16.             Console.WriteLine(message);  
    17.             return message;  
    18.         }  
    19.     }  
    20. }  
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("EntryPoint");
                Console.WriteLine(StaticClass.staticMem);
                StaticClass.ShowStaticStr("Call Static Method");
                Console.Read();
            }
    
            class StaticClass
            {
                public static string staticMem = ShowStaticStr ("Static Member");
                public static string ShowStaticStr(string message)
                {
                    Console.WriteLine(message);
                    return message;
                }
            }
        }


    结果如下:

    添加静态构造函数:

    1. class Program  
    2.    {  
    3.        static void Main(string[] args)  
    4.        {  
    5.            Console.WriteLine("EntryPoint");  
    6.            Console.WriteLine(StaticClass.staticMem);  
    7.            StaticClass.ShowStaticStr("Call Static Method");  
    8.            Console.Read();  
    9.        }  
    10.   
    11.        class StaticClass  
    12.        {  
    13.            public static string staticMem = ShowStaticStr("Static Member");  
    14.            public static string ShowStaticStr(string message)  
    15.            {  
    16.                Console.WriteLine(message);  
    17.                return message;  
    18.            }  
    19.   
    20.            static StaticClass()  
    21.            { }  
    22.        }  
     class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("EntryPoint");
                Console.WriteLine(StaticClass.staticMem);
                StaticClass.ShowStaticStr("Call Static Method");
                Console.Read();
            }
    
            class StaticClass
            {
                public static string staticMem = ShowStaticStr("Static Member");
                public static string ShowStaticStr(string message)
                {
                    Console.WriteLine(message);
                    return message;
                }
    
                static StaticClass()
                { }
            }


    结果如下:

    2.去掉静态字段调用

    1. static void Main(string[] args)  
    2.        {  
    3.            Console.WriteLine("EntryPoint");  
    4.           // Console.WriteLine(StaticClass.staticMem);   
    5.            StaticClass.ShowStaticStr("Call Static Method");  
    6.            Console.Read();  
    7.        }  
    8.   
    9.        class StaticClass  
    10.        {  
    11.            public static string staticMem = ShowStaticStr ("Static Member");  
    12.            public static string ShowStaticStr(string message)  
    13.            {  
    14.                Console.WriteLine(message);  
    15.                return message;  
    16.            }  
    17.        }  
     static void Main(string[] args)
            {
                Console.WriteLine("EntryPoint");
               // Console.WriteLine(StaticClass.staticMem);
                StaticClass.ShowStaticStr("Call Static Method");
                Console.Read();
            }
    
            class StaticClass
            {
                public static string staticMem = ShowStaticStr ("Static Member");
                public static string ShowStaticStr(string message)
                {
                    Console.WriteLine(message);
                    return message;
                }
            }


    结果如下:

    添加静态构造函数:

    1. class Program  
    2.     {  
    3.         static void Main(string[] args)  
    4.         {  
    5.             Console.WriteLine("EntryPoint");  
    6.             //Console.WriteLine(StaticClass.staticMem);   
    7.             StaticClass.ShowStaticStr("Call Static Method");  
    8.             Console.Read();  
    9.         }  
    10.   
    11.         class StaticClass  
    12.         {  
    13.             public static string staticMem = ShowStaticStr("Static Member");  
    14.             public static string ShowStaticStr(string message)  
    15.             {  
    16.                 Console.WriteLine(message);  
    17.                 return message;  
    18.             }  
    19.   
    20.             static StaticClass()  
    21.             { }  
    22.         }  
    class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("EntryPoint");
                //Console.WriteLine(StaticClass.staticMem);
                StaticClass.ShowStaticStr("Call Static Method");
                Console.Read();
            }
    
            class StaticClass
            {
                public static string staticMem = ShowStaticStr("Static Member");
                public static string ShowStaticStr(string message)
                {
                    Console.WriteLine(message);
                    return message;
                }
    
                static StaticClass()
                { }
            }


    结果如下:

    显式定义静态构造函数时的IL:

    显式定义静态构造函数的IL:


    未显式定义静态构造函数时,IL中多了一个beforefieldinit标志,此标志使得运行库能够在任何时候执行类型构造函数方法,只要该方法(静态构造函数)在第一次访问该类型的静态字段(而不是方法)之前执行即可。换句话说,beforefieldinit 为运行库提供了一个执行主动优化的许可。如果没有 beforefieldinit,运行库就必须在某个精确时间(调用之前)运行类型构造函数,即,恰好在第一次访问该类型的静态或实例字段和方法之前。当存在显式类型构造函数时,编译器不会用 beforefieldinit 标记该类型,精确的计时限制会导致 FxCop 所暗示的性能下降。

  • 相关阅读:
    20、【Linux系统编程】 exec系列函数
    3、【Linux网络编程】socket实例
    c++ 二分答案(基础应用)
    c++ 迷宫搜索(宽搜)
    c++ 广度优先搜索(宽搜)
    栈的概念
    c++ 栈的基本应用
    队列的概念
    c++ 队列的基本应用
    Knight Moves
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/4796755.html
Copyright © 2011-2022 走看看