1. 程式人生 > >C# 例項化的執行順序

C# 例項化的執行順序

首先進行細分
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();
        }

補充說明

  1. 並不是每次例項化都是上面的順序。因為靜態的成員只是在第一次例項化的時候執行,以後再例項化都不會在執行。靜態的成員意味著大家共享,且只有這一個。第一次例項化得到靜態成員後,以後大家都共享,再次例項化,沒有必要也不允許執行靜態成員的部分。
  2. 在類中如果不新增訪問修飾符,預設是靜態的
  3. 非靜態的欄位,屬性,方法,不能夠作為右值。
  4. 構造引用型別的物件時,呼叫例項構造方法之前,為物件分配的記憶體總是先被歸零,構造器沒有顯式重寫欄位,欄位的值為0或者null,例如class Test 中的
    public int mNum;mNum 預設為0
  5. C#編譯器提供了簡化語法,允許在變數定義的時候就進行初始化(C++應該不行,在構 造函式彙總)但是存在了程式碼膨脹的問題。多個欄位在定義時初始化,同時存在多個構造方法,每個構造方法都會把這些欄位初始化的程式碼搬到自己的內部,這樣造成程式碼的膨脹。
  6. 為了避免這樣情況,可以把這些欄位的初始化放到一個無參構造方法內,其他的構造方法顯式呼叫無參構造方法。
  7. 初始化欄位的兩種方法
    ①使用簡化語法:在定義的時候初始化
    ② 在構造方法內初始化。

效果圖
這裡寫圖片描述