2017年9月7日 星期四

.NET C# 靜態建構函式 static constructor 與執行個體建構函式 Instance Constructor

當我們在類別中,使用到了 static 關鍵字,不論用於類別或者類別成員上,都可以透過靜態建構函式,來進行這些靜態成員做初始化的動作。

了解更多關於 [建構函式
了解更多關於 [C# 程式設計手冊 



若該類別沒有標示 static,則這個類別裡面可以同時擁有執行個體建構函式與靜態建構函式。
如同我們所知道的,若要產生一個類別的執行個體,需要使用 new 運算子與建構函式,此時,在物件生成的時候,會使用建構函式進行相關資料的初始化;可是,靜態建構函式則是甚麼時候才能夠被執行呢?當你掌握與了解靜態建構函式的執行時間,你就可以使用靜態建構函式,針對這些靜態資料成員,進行資料初始化。
在這裡,我們使用的類別範例,如下所示;在這個類別中,有個屬性,這個屬性的實際值將會儲存在一個欄位中,而這兩者都是靜態類型的資料。另外,我們也宣告了一個執行個體的屬性 Name,這個屬性必須透過物件個體,才能夠進行存取,靜態建構式是無法直接存取到這個屬性。最後,這裡也宣告了一個靜態方法 MyMethod,要呼叫這個方法,不需要透過執行個體來呼叫,只要使用類別名稱與句點,加上這個方法名稱,MyClass.MyMethod();,就可以執行這個靜態方法了。
對於建構函式方面,我們宣告了一個執行個體預設建構函式與一個靜態建構函式。
接下來,我們將要進行一些測試,了解靜態建構函式的執行時機。
    public class MyClass
    {
        private static int _ObjectCount;

        public static int ObjectCount
        {
            get
            {
                return _ObjectCount;
            }
            set
            {
                Console.WriteLine($"要設定屬性值 {value}");
                _ObjectCount = value;
            }
        }

        public string Name { get; set; }
        public MyClass()
        {
            Console.WriteLine($"執行個體建構函式被呼叫了");
        }

        static MyClass()
        {
            ObjectCount = 100;
            Console.WriteLine($"靜態建構函式被呼叫了");
        }

        public static void MyMethod()
        {

        }
    }

測試說明

  • 沒有存取或呼叫與這個類別有關的動作
    在這個測試範例中,我們不會使用程式碼進行任何與 MyClass 類別有關的存取或者呼叫動作,在這樣的情境之下,我們來看看,靜態建構函式是否會被執行呢?
    如果你把靜態建構成員當作傳統的全域性變數來看,理論上,只要在程式一起動的時候,這些全域性變數式需要進行初始化執行動作。
    可是,當你執行底下這段程式碼的時候,控制台視窗內,卻只有 Press any key for continuing... 訊息輸出,這表示,MyClass 的靜態建構函式,並沒有被執行,也就是說,任何靜態資料成員,還沒有機會做到初始化動作。
        static void Main(string[] args)
        {
            Console.WriteLine("Press any key for continuing...");
            Console.ReadKey();
        }
    
  • 存取靜態屬性或者呼叫靜態方法
    接下來的測試程式碼,將會加入呼叫靜態方法 MyClass.MyMethod(); 或者存取一個靜態屬性或者靜態欄位 Console.WriteLine($"靜態屬性:{MyClass.ObjectCount}");
        static void Main(string[] args)
        {
            MyClass.MyMethod();
            Console.WriteLine($"靜態屬性:{MyClass.ObjectCount}");

            Console.WriteLine("Press any key for continuing...");
            Console.ReadKey();
        }
   
底下是呼叫靜態方法的輸出結果
我們可以看到,當只要程式碼有執行這個類別的靜態方法,這個靜態建構函式將會被自動呼叫,而且,更重要的是,因為它是靜態建構函式,所以,他只會被執行一次,之後不論你呼叫幾次靜態方法,這個靜態建構函式都不會再執行。
要設定屬性值 100
靜態建構函式被呼叫了
Press any key for continuing...
底下是存取了靜態屬性的輸出結果
我們可以看到,當只要程式碼有存取這個類別的靜態屬性或者靜態欄位,這個靜態建構函式將會被自動呼叫,而且,更重要的是,因為它是靜態建構函式,所以,他只會被執行一次,之後不論你存取幾次靜態屬性或者靜態欄位,這個靜態建構函式都不會再執行。
要設定屬性值 100
靜態建構函式被呼叫了
靜態屬性:100
Press any key for continuing...
  • 建立此類別的執行個體
    最後,我們在執行程式碼中,只會建立一個 MyClass 類別的執行個體,讓我們來看看,會發生甚麼狀況?
        static void Main(string[] args)
        {
            MyClass object1 = new MyClass();

            Console.WriteLine("Press any key for continuing...");
            Console.ReadKey();
        }
    
此時,您會看到該執行個體的建構函式會最後才被執行,而該類別的靜態建構函式會先被執行。
+

因此,我們可以得知,當程式碼有存取靜態物件、呼叫靜態方法、建立執行個體的時候,靜態建構函式會被自動呼叫,優先進行該類別的靜態成員的初始化;而且,這個靜態建構函式也只會在整個應用程式生命週期內,只會執行一次。
要設定屬性值 100
靜態建構函式被呼叫了
執行個體建構函式被呼叫了
Press any key for continuing...


了解更多關於 [建構函式
了解更多關於 [C# 程式設計手冊 





沒有留言:

張貼留言