zoukankan      html  css  js  c++  java
  • CLR via C#(06)- 构造器

    对于构造器,大家应该都不陌生,它主要是用来进行初始化状态的。包括实例构造器和类构造器两种,先给大家看个实际的例子。

    class Dog : Animal
        {
          

    复制代码
     private string _name;
           
    private int _age;
           
    public string Name//属性
            {
               
    get { return _name; }
               
    set { _name = value; }
            }
           
    public int Age
            {
               
    get { return _age; }
               
    set { _age = value; }
            }

           
    public static string type = "动物";//静态字段
    复制代码
      
    复制代码
    public Dog()                          //①无参实例构造函数
            {
                _name
    = "无名";
            }
           
    public Dog(string name)       //②重载,带参实例构造函数
            {
               
    this._name = name;
            }
           
    public Dog(string name, int age) //③显式调用其他构造函数
                : this()
            {
                _age
    = age;
            }
    复制代码
        
        static Dog()                      //④类构造函数                  
            {
                type
    = "狗狗";
            }

        }

    复制代码
    class Animal//基类
        {
           
    public Animal()
            {
                Console.WriteLine(
    "我是一只动物。");
            }
        }
    复制代码

    一 实例构造器

    实例构造器主要负责将类型的实例初始化到一个合理的状态。引用类型和值类型的实例构造器是有所区别的。

    1. 引用类型实例构造器

    实例构造器可以进行重载,而且可以具有不同的访问限制。上面例子中①②③都是引用类型实例构造器。

    实例构造函数和类名相同,但是没有返回类型。在ILDasm.exe中查看为.ctor。

    image

    如果我们没有定义实例构造器,那么编译器会为我们默认产生一个无参构造器。

    实例对象初始化过程

    • 为实例分配内存;
    • 初始化附加成员,包括方法表指针和SyncBlockIndex变量(我们已经在跟小静读CLR via C#(03中已经提到过)。
    • 调用实例构造器进行初始化。

    在调用构造函数前,变量被初始化为0或者null,所以没有被构造器改变的变量在实例创建后将保持0值。例如下面的age字段保持0值

    image

    image

    image

    调用顺序

    如果类没有显示定义构造器,编译器会自动生成一个无参构造器,调用基类的无参构造器。例如

    public class Animal{}

    相当于

    public class Animal

    {

       public Animal():base(){}

    }

    如果类的修饰符为static(sealed和abstract),编译器不会默认生成构造器;

    如果基类没有提供无参构造器,那么派生类必须显示调用一个构造器,否则编译错误。

    如果存在继承关系,派生类在使用基类的字段之前应该先调用基类的构造器。如果派生类没有显式调用基类构造器,则编译器会自动产生调用基类无 参构造器的代码,沿着继承层次一直到System.Object的无参构造器位置。例如下面,调用Dog dog=new Dog()方法的结果。

    image

    class Dog:Animal。。。

    image

    Dog()方法IL代码

    image

    代码爆炸?

    为了防止构造器重载时大量重复赋值造成代码膨胀,我们建议将公共的初始化语句放在一个构造函数中,然后其他的构造器显式调用该构造器。

    image

    2. 值类型实例构造器
    • 值类型没有默认产生的无参构造器,也不允许我们定义无参构造器。但是我们可以自定义带参数的构造器。

    image

    • 不允许在值类型中内联实例字段的初始化。下面的例子会产生编译错误。
      struct TestStruct
          { 
             
      partial int number=5;
          }
    • 值类型带参构造函数必须对所有实例字段进行初始化才可以。如果有变量没有初始化,就会报错。

    image 

    如果不想对所有字段一一初始化,有一种替代方案:

    复制代码
      struct Dog
        {
            
    public int age;
            
    public string name;
            
    public Dog(string Name)
            {
                
    this = new Dog();
                name 
    = Name;
            }
        }
    复制代码

    在值类型构造器中,this代表值类型本身的一个实例,用New创建的值类型实例赋给this时,会将所有字段置零。所以这个方案可以编译通过。

    • 带参构造函数定义之后需要用new显式调用才能执行。否则值类型的字段会保持0或Null值。

    image     image

    类构造器

    • 类构造器适用于引用类型(包括接口)和值类型,用来设置类的初始状态。类中并没有默认产生的类构造器,需要我们显式构造,标记为static方法。在元数据表中对应.cctor

    image

    • 类构造器只能有一个,不能进行重载。而且不能含参数。类构造器的目的是初始化类的静态成员,它只能访问静态成员,不能访问实例成员。
    • 类构造器的访问限制是私有的,但是我们不能在类构造器前添加访问修饰符,private也不行,否则会产生编译错误,这样做是为了防止开发人员调用该方法。它的调用是由CLR负责的,我们应该避免编写需要以特定顺序调用类构造器的代码。
    • 类构造器不要调用其基类的类构造器。因为基类的静态成员并没有被派生类所继承,它只是编译时静态绑定。
    • 类构造器的调用顺序和实例构造器相似的,首先静态字段被初始化,然后在构造其中被重新赋值。例如:

    class Dog : Animal

    {

    public static string type = "动物";//静态字段

    //类构造函数

    static Dog()

    {

    type = "狗狗";

    }

    }

    Console.WriteLine(Dog.type);

    image

    礼品盒 本节小测

    image

    Dog的age字段值是什么呢?

    A.0             B.5          C.其他

     文章出处:跟小静读CLR via C#

  • 相关阅读:
    angularJS中的MVC思想?
    angularJs初体验,实现双向数据绑定!使用体会:比较爽
    原生JS去解析地址栏的链接?超好用的解决办法
    HDCMS多图字段的使用?
    sublime添加到鼠标右键打开文件的方法?
    Ajax做列表无限加载和Ajax做二级下拉选项
    Atitit.获取某个服务 网络邻居列表 解决方案
    Atitit. 注册表操作查询 修改 api与工具总结 java c# php js python 病毒木马的原理
    Atitit. 注册表操作查询 修改 api与工具总结 java c# php js python 病毒木马的原理
    Atitit.prototype-base class-based  基于“类” vs 基于“原型”
  • 原文地址:https://www.cnblogs.com/fireshadow23/p/3640644.html
Copyright © 2011-2022 走看看