• CLR via C#-类型构造器


    类型构造器

    除了实例构造器,CLR还支持类型构造器,也称为静态构造器、类构造器或者类型初始化构造器。类型构造器可应用于引用类型和值类型。

    实例构造器的作用是设置类型的实例的初始状态。对应地,类型构造器的作用是设置类型的初始状态。


    类型默认没有类型构造器

    如果定义也只能定义一个,此外类型构造器永远没有参数,以下代码展示了如何在C#中为引用类型和值类型定义一个类型构造器。

    internal sealed class SomeRefType{
        static SomeRefType(){}
    }
    internal struct SomeValType{
        static SomeValType(){}
    }

    定义类型构造器类似于定义无参实例构造器,区别在于必须标记为static。

    类型构造器是私有的

    C#把他们自动标记为private,如果在源代码中显式将类型构造器标记为private或者其他访问修饰符,C#编译器会报错。

    之所以必须私有,是为了防止任由开发人员写的代码调用它,对他的调用总是由CLR负责。

     


    类型构造器只执行一次

    类型构造器的调用比较麻烦。JIT编译器在编译一个方法时,会查看代码中都引用了哪些类型。

    任何一个类型定义了类型构造器,JIT编译器都会检查针对当前AppDomain,是否已经执行了这个类型构造器。

    如果构造器从未执行,JIT编译器会在他生成的本机native代码中添加对类型构造器的调用。

    如果类型构造器已经执行,JIT编译器就不添加对他的调用,因为他知道类型已经初始化好了。

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

    所以非常适合在类型构造器中初始化类型需要的任何单实例对象Singleton。

    不要在两类型的类型构造器中写相互引用的代码

    单线程中的两个类型构造器包含相互引用的代码可能出问题。

    假定A的类型构造器包含了引用sB的代码,B的类型构造器包含了A的代码。

    在这种情况下,CLR仍然保证每个类型构造器的代码只被执行一次。

    但是完全有可能在A的类型构造器还没有完全执行完毕的前提下就开始执行B的类型构造器。

    不要在值类型中定义类型构造器

    虽然能在值类型中定义类型构造器。但永远不要真的这么做,因为CLR有时不会调用值类型的静态构造器。


    使用内联字段初始化语法静态字段

    类型构造器中的代码只能访问类型的静态字段,并且他的常规用途就是初始化这些字段。和实例字段一样,C#提供了一个简单的语法来初始化类型的静态字段。

    internal sealed class SomeType{
        private static Int32 s_x=5;    
    }

    值类型允许使用内联字段初始化静态字段

    虽然C#不允许值类型为他的实例字段使用内联字段初始化语法,但可以为静态字段使用。换句话说,将前面定义的SomeType类型从class改为struct,那么代码也能通过编译。

    生成上述代码时,编译器自动为SomeType生成一个类型构造器,就好像源代码本来是这样写的。

    internal sealed class SomeType{
        private static Int32 s_x;
        static SomeType(){ s_x = 5 }
    }

    类型构造器不应调用基类型的类型构造器

    这种调用之所以没必要,是因为类型不可能有静态字段是从基类型分享或继承的。

     


    初始化字段的顺序

    internal sealed class SomeRefType{
        private static Int32 s_x = 5;
        static SomeType(){
            s_x = 10;
        }
    }

    在这个例子中,C#编译器只生产一个类型构造器方法,他首先将s_x初始化为5,再把它修改成10.

    换言之,当C#编译器为类型构造器生成IL代码时,他首先生成的是初始化静态字段所需的代码,然后才会添加你的类型构造器方法中显式包含的代码。

  • 相关阅读:
    用原生JS判断素(质)数,并找出100~1000之间的所有素(质)数
    用原生JS找出所有的水仙花数
    break、continue和return语句的区别
    用原生JS写16进制随机颜色
    JavaScript函数
    JavaScript数组
    JavaScript流程控制
    新的开始,新的历程
    异常处理
    DictionaryBase
  • 原文地址:https://www.cnblogs.com/errornull/p/9769433.html
Copyright © 2020-2023  润新知