总结:CLR Via C#(第八章):构造器

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

1、 类只能拥有类自己的实例构造器;实例构造器不能被继承;

2、 以下修饰符不能用于实例构造器:virtualnewoverridesealedabstract

如果类的修饰符为abstract,那么默认构造器可访问性为protected,否则为public

3、 如果基类没有提供无参构造器,那么类必须显示调用基类的构造器,否则编译出错;

   public abstract class Base2

    {

        public Base2(int i)

        {

            Console.WriteLine("Base2:" + i);

        }

    }

    //ErrorBase2方法没有采用“”个参数的重载

    //public class Child2 : Base2

    //{

    //}

    public class Child2: Base2      

    {

         public Child2(int i):base(i)

        {

            Console.WriteLine("Child2:" + i);

        }

    }

如果类的修饰符为staticsealedabstract),那么编译器不会在类的定义中生成一个默认的构造器;

4、 类的实例构造器在访问基类继承的任何字段之前,必须调用其基类的构造器;

5、 在构造器中不能调用任何虚方法(虽然编译无错),这样会影响所创建的对象,导致无法预测;

    public abstract class Base2

    {

        public Base2()

        {

            Virtual_Fn();

        }

        public virtual void Virtual_Fn()

        {

            Console.WriteLine("Base2:Virtual_Fn");

        }

    }

    public class Child2 : Base2

    {

        public Child2()

        {

            Virtual_Fn();

        }

        public override void Virtual_Fn()

        {

            Console.WriteLine("Child2:Virtual_Fn");

        }

    }

 

输出:

Child2:Virtual_Fn

Child2:Virtual_Fn

 

6、 下面的代码中,类有三个构造器,所以编译器产生三次初始化m_xm_sm_d——每次构造器一次;

     internal sealed class SomeType {

         private Int32 m_x = 5;

         private String m_s = "Hi there";

         private Double m_d = 3.14159;

         private Byte   m_b;

 

         // Here are some constructors.

         public SomeType()         { /* ... */ }

         public SomeType(Int32 x) { /* ... */ }

         public SomeType(String s) { /* ...; */ m_d = 10; }

     }

可以将公共初始化语句放到一个单独的初始化构造器中,以减少生成的代码大小;

改造如下:

internal sealed class SomeType

    {

        // Do not explicitly initialize the fields here

        private Int32 m_x;

        private String m_s;

        private Double m_d;

        private Byte m_b;

 

        // This method MUST be called by all constructors.

        public SomeType()

        {

            m_x = 5;

            m_s = "Hi there";

            m_d = 3.14159;

            m_b = 0xff;

        }

 

        // This constructor sets all fields to their default, then changes m_x.

        public SomeType(Int32 x) : this()

        {

            m_x = x;

        }

 

        // This constructor sets all fields to their default, then changes m_s.

        public SomeType(String s) : this()

        {

            m_s = s;

        }

    }

 

实例构造器和结构(值类型):

1、 CLR允许创建值类型的实例,但是无法阻止值类型的初始化,因此值类型实际上不需要在其内部定义构造器;

值类型的构造器只有在被显式调用时才会执行;

C#不允许值类型显式定义无参构造器;

    //Error:结构不能包含显式的无参数构造函数

    //public struct Point

    //{

    //    public Point()

    //    {

    //    }

//}

2、 值类型的构造器必须初始化值类型的所有字段;

    public struct Point

    {

        private int m_x;

        private int m_y;

 

        // Error:必须给所有字段初始化

        public Point(int x)

        {

            m_x = x;

            // m_y没有被初始化

        }

    }

类型构造器(静态构造器):

1、 类型构造器可以用于接口、引用类型、值类型;

2、 一般不在类型内部定义类型构造器,如果定义,不能超过一个;

3、 C#自动将类型构造器标记为private,类型构造器前不能有访问修饰符;

    public class Base1

    {

        // Error静态构造器必须无参

        static Base1(int i)

        {

        }

 

        // Error类型构造器不允许出现访问修饰符

        private static Base1()

        {

        }

 

    }

4、 永远不要在值类型中定义类型构造器,虽然可以这样做,因为CLR中存在不调用值类型的静态构造器的情况;

   internal struct SomeValueType

    {

        public int m_x;

        static SomeValueType()

        {

            Console.WriteLine("Static 构造器");

        }

}

        static void Main(string[] args)

        {

            SomeValueType some = new SomeValueType();

            Console.WriteLine(some.m_x);

            Console.ReadLine();

     }

         输出:0

         静态构造器没有执行;

5、使用静态构造器时,要注意多线程同步;

 

原文地址:https://www.cnblogs.com/LeimOO/p/1654304.html