1. 程式人生 > >《隨筆一》——C#中的“靜態建構函式、物件初始化語句”

《隨筆一》——C#中的“靜態建構函式、物件初始化語句”

 


靜態建構函式


● 我們在使用類中的靜態成員時,先要初始化這些成員。 在宣告靜態成員時、可以同時提供一個初始值。 但有時候我們需要執行更復雜的初始化操作, 這應該怎麼辦呢?

● 我們可以把建構函式宣告成static的, 一般來說, 靜態的建構函式初始化類的靜態欄位。

關於靜態建構函式應注意的有:

●  那麼一個類只能有一個靜態建構函式,而且不能帶引數、沒有返回值。  也不能有訪問修飾符(比如private)。 而且宣告時使用static 關鍵字作為前輟。

● 那麼一個類既可以有靜態建構函式也可以有例項建構函式。

 跟靜態成員函式類似, 靜態建構函式不能訪問所在類的例項成員, 所以也不能使用this訪問器。

 

● 不能在程式中顯式呼叫靜態建構函式,系統會自動呼叫它們,在:

只要一個類有靜態建構函式,當我們建立第一個類例項時,都會呼叫靜態建構函式、

只要一個類有靜態建構函式,類的任何靜態成員被引用之前。

在這兩種情況下,會首先呼叫靜態建構函式, 之後例項化類或訪問靜態成員。應注意的是: 其實我們建立了多個個類例項, 其靜態建構函式都只調用一次。

下面看一個程式程式碼:

namespace Ch05Ex03
{
    class RandomNum
    {
        static int RandomKey;
        int aa;
        int bb;
        static RandomNum()
        {
            RandomKey = 15;
            WriteLine("靜態建構函式被呼叫!");
        }
        public RandomNum(int _aa,int _bb)
        {
            aa = _aa;
            bb = _bb;
            WriteLine("\n例項建構函式被呼叫!");
        }
        public void Show()
        {
            WriteLine($"輸出RandomKey的靜態成員的值:{RandomKey}");
            WriteLine($"輸出aa的靜態成員的值:{aa}");
            WriteLine($"輸出bb的靜態成員的值:{bb}");
            WriteLine();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            RandomNum a = new RandomNum(2,3);
            RandomNum b = new RandomNum(5,6);
            a.Show();
            b.Show();
            ReadKey();
        }
    }
}
輸出是結果為:

靜態建構函式被呼叫!

例項建構函式被呼叫!

例項建構函式被呼叫!
輸出RandomKey的靜態成員的值:15
輸出aa的值:2
輸出bb的的值:3

輸出RandomKey的靜態成員的值:15
輸出aa的值:5
輸出bb的的值:6

在該程式中, 我們首先建立了該類的兩個例項,分別為它填了兩個實參, 我可以看到輸出結果,不管建立多少個例項,  靜態建構函式只調用只一次, 其次就是呼叫建立該例項的對應的例項建構函式, 上面的程式呼叫的是帶兩個形參的例項建構函式。 呼叫順序為你建立例項的順序。

那麼每一個例項都有一個靜態成員的值,它被所有類例項所共享。


物件初始化語句


namespace Ch05Ex03
{
    class RandomNum
    {
        
       public int aa;
       public int bb; 
       public RandomNum()
        {
            aa = 55;
            bb = 66;
            WriteLine("預設的建構函式被呼叫!");
        }
       public RandomNum(int _aa,int _bb)
        {
            aa = _aa;
            bb = _bb;
            WriteLine("\n例項建構函式被呼叫!\n");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            RandomNum pt1 = new RandomNum(); //呼叫預設的建構函式

            //使用物件初始化語句初始化該類的公有欄位       
            RandomNum pt2 = new RandomNum { aa = 7, bb = 8 }; //呼叫預設建構函式
            RandomNum pt3 = new RandomNum (2,3){ aa = 5, bb = 6 }; // 呼叫帶參的例項建構函式

            WriteLine($"輸出pt1中的值:{pt1.aa} , {pt1.bb}");
            WriteLine($"輸出pt2中的值:{pt2.aa} , {pt2.bb}");
            WriteLine($"輸出pt3中的值:{pt3.aa} , {pt3.bb}");
            ReadKey();
        }
    }
}


輸出結果為:

預設的建構函式被呼叫!
預設的建構函式被呼叫!

例項建構函式被呼叫!

輸出pt1中的值:55 , 66
輸出pt2中的值:7 , 8
輸出pt3中的值:5 , 6

●  如果一個類如果有公有欄位時, 我們即可以在建構函式中初始化, 我們也可以在類外定義類例項時,用該例項物件一一初始化公有欄位。類似於這樣:

            pt1.aa = 100;
            pt1.bb = 200;

●  其實還有還有一種方式是:  使用物件初始化語句來初始化該類的公有欄位。 這樣,我們就可以在建立物件的例項時, 設定欄位和屬性的值。

●  該語句有兩種形式:

類名 例項名 = new 類名 {欄位名稱 = 初始值};
類名 例項名 = new 類名(實參表) {欄位名稱 = 初始值};

注意:  一種形式包括建構函式的引數列表,另一種不包括。其中一種甚至不使用實參列表的圓括號。

注意: 使用這樣形式初始化欄位和屬性, 該欄位和屬性必須是public的。

注意: 初始化發生在構造方法執行之後。 所以在建構函式中設定的實參值會在物件初始化中重置為相同或不同的值。在上述程式該程式碼中:

  RandomNum pt3 = new RandomNum (2,3){ aa = 5, bb = 6 }; // 呼叫帶參的例項建構函式

我們在建構函式中的實參表設定值2、3, 又在 { } 中設定了值5、6, 那麼首先呼叫帶參的建構函式初始化,之後又被 { } 該列表中設定的值初始化,所以 輸出的值是 5、6, 而不是2、3.

注意:

   RandomNum pt2 = new RandomNum { aa = 7, bb = 8 }; //呼叫預設建構函式

該程式碼呼叫的是預設的建構函式, 因為他沒有提供實參表。