实例构造器和类(引用类型)


构造器是允许将类型的实例初始化为良好状态的一种特殊方法。构造器方法在“方法定义元数据表”中始终教.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
在该构造器中先调用无参数的构造器(如上红色),然后再进行本身构造器的实例化。
由此可见,这样很好的防止了代码膨胀。
posted @ 2011-05-17 17:44  Raysonxin  阅读(297)  评论(0编辑  收藏  举报