首先进行细分 1.类的成员分为:字段,属性,方法,构造函数
2.成员修饰符:静态成员,实例成员
不考虑继承的关系执行顺序为 1.静态字段 2.静态构造方法 3.实例字段 4.实例构造方法 其中 属性和方法只有在调用的时候才执行。 下面是一段代码例子
定义了一个类,当我们实例化的时候 Test test = new Test(); 通过VS2008仿真 执行过程是 0. 静态的最先执行,仿真编译略过 1. F11 执行 public int mNum2=2; //简单的初始化字段 2. private int mNum3 = 3; private int mNum4 = 4; 3. public Test() { temp = 1;mNum = 0; } //构造函数
以上是执行的顺序: 与上面描述的的执行过程稳和,属性和字段跳过。public int mNum;也执行了,只不过系统默认赋值为空(null)或者0,系统西东除了的仿真时候跳过。 class Test { public static int temp; public int mNum; public int mNum2=2; public void look() { Console.WriteLine("看我,我是test"); Console.WriteLine("mNum={0}", mNum); } private int mNum3 = 3; private int mNum4 = 4; public int Num3 { get { return mNum3; } set { mNum3= value; } } public Test() { temp = 1; mNum = 0; } }当存在继承关系的时候,执行的顺序。 1. 子类的静态字段 2. 子类的静态构造方法 3. 子类的实例字段 4. 父类的静态字段 5. 父类的静态构造方法 6. 父类的实例字段 7. 父类的实例构造方法 8. 子类的实例构造方法 下面是例子
1. 首先执行 class A中 int x = 1;,执行所有已经初始化后的字段,当执行到构造函数首执行父类字段 2. int sd = 6; 3. public A(),首先会去执行父类。 4. 0. 静态的最先执行,仿真编译略过 1. F11 执行 public int mNum2=2; //简单的初始化字段 2. private int mNum3 = 3; private int mNum4 = 4; 3. public Test() { temp = 1;mNum = 0; } //构造函数 5. public A() { PrintFields(); look(); }// 执行子类中自己的构造函数 6. public virtual void PrintFields() ;执行自己类中有意义的虚函数 7. 执行调用父类的函数 look(); 8. 接下来就将要执行 class B 中的内容了。过程类似,先一步一步的执行A类,在执行Test类,实现继承。 9. 忽略部分细节,降调B类中的细节。 int z=2; public B() 运行到这里的时候,再次执行到 public A() { PrintFields(); look(); } 的构造函数的时候,由于执行的是实例化B类,又在B类中重写了PrintFields();,实现多态。所以执行 public override void PrintFields() { Console.WriteLine("x={0},y={1}", "b", z); } 所以此时的 z=2; 而不是 public B() { z = -1; } 中的z=-1,因为还没有执行到它,随后才执行子类中的构造函数。10. 接下来是执行C类的实例化,C类中没有写C的构造函数,但是还是执行到了 B类(它的父类)中int z=2;,是因为,默认给写了无参的C类构造函数。 相当与 public C(){} 11. 所以任然能够继承,执行 public override void PrintFields() { Console.WriteLine(“j={0},k={1}”, “CC”, y); }
class A :Test { int x = 1; public A() { PrintFields(); look(); } int c; int sd = 6; public virtual void PrintFields() { Console.WriteLine("j={0},k={1}", "AA", "AA"); } } class B : A { int y; int z=2; public B() { z = -1; } public override void PrintFields() { Console.WriteLine("x={0},y={1}", "b", z); } } class C : B { int x = 1; int y = 3; public override void PrintFields() { Console.WriteLine("j={0},k={1}", "CC", y); } } static void Main(string[] args) { Test test = new Test(); A a = new A(); B b = new B(); C c = new C(); Console.ReadKey(); }补充说明
并不是每次实例化都是上面的顺序。因为静态的成员只是在第一次实例化的时候执行,以后再实例化都不会在执行。静态的成员意味着大家共享,且只有这一个。第一次实例化得到静态成员后,以后大家都共享,再次实例化,没有必要也不允许执行静态成员的部分。在类中如果不添加访问修饰符,默认是静态的非静态的字段,属性,方法,不能够作为右值。构造引用类型的对象时,调用实例构造方法之前,为对象分配的内存总是先被归零,构造器没有显式重写字段,字段的值为0或者null,例如class Test 中的 public int mNum;mNum 默认为0C#编译器提供了简化语法,允许在变量定义的时候就进行初始化(C++应该不行,在构 造函数汇总)但是存在了代码膨胀的问题。多个字段在定义时初始化,同时存在多个构造方法,每个构造方法都会把这些字段初始化的代码搬到自己的内部,这样造成代码的膨胀。为了避免这样情况,可以把这些字段的初始化放到一个无参构造方法内,其他的构造方法显式调用无参构造方法。初始化字段的两种方法 ①使用简化语法:在定义的时候初始化 ② 在构造方法内初始化。效果图
