zoukankan      html  css  js  c++  java
  • 实例构造器和类(引用类型)


    构造器是允许将类型的实例初始化为良好状态的一种特殊方法。构造器方法在“方法定义元数据表”中始终教.ctor。
    创建一个引用类型的实例时,首先为实例的数据字段分配内存,然后初始化对象的附加字段(类型对象指针呵呵同步块索引),最后调用类型的实例构造器来设置对象的初始状态。
    实例构造器永远不能被继承。
    如果类的修饰符为abstract,那么编译器生成的默认构造器的可访问性就为protected;否则,构造器会被赋予public可访问性。如果基类没有提供无参数构造器,那么派生类必须显示调用一个基类构造器,否则编译器会报错。如果类的修饰符为static(sealed和abstract),编译器根本不会再类的定义中生成一个默认构造器。
    C#编译器提供一个简化的语法,允许以“内联”方式初始化实例字段。但在幕后,它会将这种语法转换成构造器方法中的代码来执行初始化。这同时提醒我们注意代码的膨胀效应。
    所谓内联,是指在代码中直接赋值来初始,而不是通过构造器。
        internal sealed class SomeType
        {
            public SomeType() { }
            public SomeType(Int32 x) { }
            public SomeType(String s) { }

            private Int32 m_x = 5;
            private String m_s = "Hello World";
            private Double m_d = 3.14159;
            private Byte m_b;
        }
    编译器为这三个构造器方法生成代码时,在每个方法开始的位置,都会包含用于初始化m_x,m_s和m_d的代码。在这些初始化代码之后,编译器会插入对基类构造器的调用。再然后,会插入构造器自己的代码。查看该类的IL代码,发现有三个构造方法:
     
    每个.ctor方法中都会初始化m_x,m_s和m_d。如下IL代码(这里只是贴出了无参数构造器的IL代码):
    .method public hidebysig specialname rtspecialname
            instance void  .ctor() cil managed
    {
      // 代码大小       43 (0x2b)
      .maxstack  8
      IL_0000:  ldarg.0
      IL_0001:  ldc.i4.5
      IL_0002:  stfld      int32 ctor.SomeType::m_x
      IL_0007:  ldarg.0
      IL_0008:  ldstr      "Hello World"
      IL_000d:  stfld      string ctor.SomeType::m_s
      IL_0012:  ldarg.0
      IL_0013:  ldc.r8     3.1415899999999999
      IL_001c:  stfld      float64 ctor.SomeType::m_d
      IL_0021:  ldarg.0
      IL_0022:  call       instance void [mscorlib]System.Object::.ctor()
      IL_0027:  nop
      IL_0028:  nop
      IL_0029:  nop
      IL_002a:  ret
    } // end of method SomeType::.ctor
    如果有几个以初始化的实例字段和大量重载的构造器方法,可考虑不是在定义字段时初始化,而是创建单个构造器来执行这些公共的初始化。然后,让其他构造器显示调用这个公共初始化构造器。这样可以减少生成的代码。如下演示:
            public SomeType1()
            {
                m_x = 5;
                m_s = "Hello World";
                m_d = 3.14159;
                m_b = 0xff;
            }
            public SomeType1(Int32 x)
                : this()
            {
                m_x = x;
            }
            public SomeType1(String s)
                : this()
            {
                m_s = s;
            }
            public SomeType1(Int32 x, String s)
                : this()
            {
                m_s = s;
                m_x = x;
            }
        }
    编译后,会发现无参数的构造函数IL代码与上面的IL一样,而在SomeType1(Int32 x)中的IL代码中如下:
    .method public hidebysig specialname rtspecialname
            instance void  .ctor(int32 x) cil managed
    {
      // 代码大小       17 (0x11)
      .maxstack  8
      IL_0000:  ldarg.0
      IL_0001:  call       instance void ctor.SomeType1::.ctor()
      IL_0006:  nop
      IL_0007:  nop
      IL_0008:  ldarg.0
      IL_0009:  ldarg.1
      IL_000a:  stfld      int32 ctor.SomeType1::m_x
      IL_000f:  nop
      IL_0010:  ret
    } // end of method SomeType1::.ctor
    在该构造器中先调用无参数的构造器(如上红色),然后再进行本身构造器的实例化。
    由此可见,这样很好的防止了代码膨胀。
  • 相关阅读:
    apply()与call()的区别
    VS Code 配置vue开发环境
    settimeout 和 setinterval
    JAVA内存泄漏和内存溢出的区别和联系
    Oracle Distinct(过滤重复)用法
    Oracle Order By排序用法详解
    Oracle Select语句
    登陆权限--token的使用
    登陆权限--token 的生成和验证
    MySQL基础增删改查
  • 原文地址:https://www.cnblogs.com/rayxin/p/2049123.html
Copyright © 2011-2022 走看看