CLR类型设计之方法与构造器

 

           不管学习那门语言都要学习函数体,C#,JAVA,PHP,都会涉及到函数体,而C#的函数体成员并很多,方法和构造器就是函数体成员之一,函数体成员还包括但不限于:方法,属性,构造器,终结器,运算符及索引器。html

            方法就是某个类相关的函数,也能够返回简单的基元类型或者什么也不反回,方法能够定义其公开性,若是使用static修饰符则变为静态方法。c#

            属性是能够从客户端访问到的函数组,访问形式和访问类相同,C#为读写类中的属性提供了专用语法。数组

            构造器是实例化对象时自动调用的特殊函数,必须与所属的类同名,且不能有返回类型,构造器用于初始化字段的值,可经过不一样参数进行重载。安全

            终结器相似与构造函数,可是CLR检测到再也不须要某个对象时调用他,他的名称与类相同,但前面有一个~符号 并发

            运算符执行的最简单操做就是“+’“-’“*’“/’这些基本运算,C#也支持重载运算符ide

             索引器容许对象以数组的或集合的方式进行索引。函数

             构造器性能

              以上就是函数体的基本成员和方法的基本定义,接下来咱们先说一下构造器,为何说构造器?学习

              由于构造器实际上会帮咱们很好的理解方法一个类的初始化过程,咱们会发现不管是一个对象实体或是方法,大部分都会放在cs文件中,而构造器是初始化对象的,我创建了一个Student的类里面只有一个字段一个函数体,在Main函数中我初始化了Student类,运行就会发现构造器函数以及执行,而且调用了方法writethis

             能够发现,当建立一个类型的实例时:

             1)为实例的字段分配内存。

             2)初始化对象的附加字段(类型对象指针和同步块索引)。

             3)调用类型的实例构造器来设置对象的初始状态。

运行后输出的结果    

               实例构造器永远不能被继承。

               由于实例构造器不能被继承,类只有类本身定义的实例构造器,因此就不能用virtual,new,override,sealed,abstract修饰符来定义构造器。 类型构造器能够用于接口(C#不容许这样作),引用类型,值类型。实例构造器用来设置一个类型某个实例的初始化状态,类型构造器用来设置一个类型的初始化状态。默认状况下,若是定义的类没有显式的定义一个构造器,编译器会默认的定义一个无参的构造器。在默认构造器的实现中,它只是简单的调用了基类的无参构造器。

              当咱们在值类型里面定义了一个类型构造器时,CLR不必定会调用这个静态构造器,例子建立的是无参类构造器,会在第一次初始化时建立,因此咱们再次实例化stu的时候,控制台会输出“我是函数方法1”,若是一个类构造器的方法里,引入了其余类型定义了类型构造器,JIT会检测是否已经在AppDomain里面执行过。若是没有执行,则发起对类型构造器的调用,不然不调用。

                 当程序运行后,线程会开始执行并最终获取调用构造器的代码。实际上有可能会是多个线程执行同一个方法,CLR想要确保一个类型构造器在一个AppDomain里面只执行一次,当一个类型构造器被调用时,调用的线程会获取一个互斥的线程同步锁,这时若是有其余的线程在调用,则会阻塞。当第一个线程执行完后离开,其余的线程被唤醒并发现构造器的代码执行过了,因此不会继续去执行了,从构造器方法返回。CLR经过这种方式来确保构造器仅仅被执行一次。

             提示:

             因为CLR会确保类型构造器在每个AppDomain里面只会执行一次,是线程安全的。因此若是要初始化任何单例对象(singleton object),放在类型构造器里面是再合适不过了。

      静态构造器

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

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

    静态构造器在类的静态成员初始化以后执行.或者说编译器会将静态成员初始化语句转换成赋值语句放在静态构造器执行的最开始.

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

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

           

    类型构造器性能

                  调用类型构造器并不那么简单,JIT编译器不得不决定是否生成调用它的代码,而且CLR要确保调用是线程安全的。当编译器决定发起一个调用来执行类型构造器,它必须判断是否应该这样作,有两种可能性:

                   1.JIT在建立类型的第一个实例的代码以前当即发起或者在访问类的非继承的字段,成员的代码以前当即调用

                    2.JIT在首次访问一个静态字段,静态方法,实例方法,或调用一个实例构造器的代码以前某个时间调用,由于CLR要确保静态构造器在其余成员被访问以前运行。

                  构造函数中,还有一个特殊的存在,  readonly关键字是一个可在字段上使用的修饰符。 当字段声明包括 readonly 修饰符时,该声明引入的字段赋值只能做为声明的一部分出现,或者出如今同一类的构造函数中。

   能够说readonly通常只在构造器初始化的时候赋值,其他的时候不能改变他的值。

         扩展方法

              c# 扩展方法出来已久,介绍扩展方法的文章也不少,简单点说就是能够在不改变现有类的状况下给这个类添加方法。我以为扩展方法的最大意义在于咱们能够给那些咱们根本没法修改的类,好比String,添加咱们自定义的方法。既然没法经过修改来添加,那就只能经过扩展了。在使用扩展方法时,能够像调用实例方法那样调用静态方法。这就很大程度的方便了代码的开发。

                

       扩展方法的基本原则:

       (1).C#只支持扩展方法,不支持扩展属性、扩展事件、扩展操做符等。

      (2).扩展方法(第一个参数前面是this的方法)必须在非泛型的静态类中声明,扩展方法必须有一个参数,并且只有第一个参数使用this标记。

      (3).C#编译器查找静态类中的扩展方法时,要求这些静态类自己必须具备文件做用域。

      (4).C#编译要求“导入”扩展方法。(静态方法能够任意命名,C#编译器在寻找方法时,须要花费时间进行查找,须要检查文件做用域中的全部的静态类,并扫描它们的全部静态方法来查找一个匹配)

      (5).多个静态类能够定义相同的扩展方法。

      (6).用一个扩展方法扩展一个类型时,同时也扩展了派生类型。 

        扩展方法不易乱用,尤为是在基类中扩展,其全部派生类都会有这个方法,很容易形成不该该出现的地方出现,另外扩展方法必须为顶级类,不能在嵌套类中使用扩展方法。扩展方法能够扩展不少种类型,包括但不限于,扩展委托,枚举,接口。

         因为扩展方法能够在不少.netformwork提供的类库上使用扩展方法,例如:Enumerable,Queryable,String等等,也能够用于扩展异常方法,扩展枚举。本文篇幅有限,因此咱们举其中一个示例。咱们写一个以下的String扩展类,string是c#里面最最经常使用的类,和它的使用频度比起来,它的操做确少的可怜,实例方法只有三十个左右,静态方法只有十多个,
                  首先咱们把string类最经常使用的静态方法IsNullOrEmpty扩展成“实例”方法:

                  只须要创建一个新的静态类,而后写一个方法名,将须要扩展的类参数前加上this就能够了。

                 

             在调用的时候,就能够直接把静态方法IsNullOrEmpty扩展成“实例”方法来调用。是否是就方便了不少,这只是一个抛砖引玉的例子。

           

            在这里推荐一篇博文,博文里讲了不少具体的方法实例。

            http://www.cnblogs.com/ldp615/archive/2009/08/07/1541404.html

相关文章
相关标签/搜索