一直以來對static不是很清楚, 所以順手來做個筆記
靜態類別和靜態成員可以用來建立資料或函式, 即不需要透過new 類別名稱產生執行個體就可以存取
靜態類別
類別宣告為靜態時, 其中只會包含靜態的成員, 當載入包含靜態類別的程式或命名空間時,.NET Framework Common Language Runtime (CLR) 也會自動載入這些類別。
靜態類別的主要特色如下:
-
只包含靜態成員。
-
無法執行個體化 (Instantiated)。
-
為密封類別, 所以無法被繼承。
-
無法包含執行個體建構函式。
-
可以宣告靜態建構函式(非靜態類別也可宣告),以指定初始值或設定靜態狀態(靜態建構函式下面繼續介紹)
[使用時機] 不須為方法建立執行個體
static class CompanyInfo
{
public static string GetCompanyName() { return "CompanyName"; }
public static string GetCompanyAddress() { return "CompanyAddress"; }
//...
}
靜態成員
靜態成員的主要特色如下:
- 建立的執行個體, 不能存取靜態成員(欄位、屬性、方法、事件...)
- 靜態欄位和靜態事件只會有一個複本存在, 而靜態方法和靜態屬性也只能存取靜態欄位和靜態事件
- 常用來代表不會隨物件改變的資料
public class Automobile
{
public static int NumberOfWheels = 4;
public static int SizeOfGasTank
{
get
{
return 15;
}
}
public static void Drive() { }
public static event EventType RunOutOfGas;
//other non-static fields and properties...
}
第一次存取靜態成員以及呼叫靜態建構函式 (如有呼叫) 之前,會先初始化靜態成員。
Automobile.Drive();
int i = Automobile.NumberOfWheels;
靜態建構函式
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.MyMethod(), 此時去呼叫靜態建構函式, 但是其中針對靜態屬性ObjectCount設定100, 此時會呼叫setter先印出"要設定屬性值 {value}"(value為100)後並把值給ObjectCount, 再印出"靜態建構函式被呼叫了"
實驗二: 上述實驗再加一行直接存取MyClass.ObjectCount, 可以發現靜態建構函式指呼叫了一次
實驗三: 直接產生執行個體, 可以發現靜態建構函式先被呼叫, 才呼叫建構函式
由此可以得知當程式碼有存取靜態物件、呼叫靜態方法、建立執行個體的時候,靜態建構函式會被自動呼叫,優先進行該類別的靜態成員的初始化;而且,這個靜態建構函式也只會在整個應用程式生命週期內,只會執行一次。
引用參考:
https://dotblogs.com.tw/chris0920/2010/03/15/14031
https://csharpkh.blogspot.com/2017/09/static-constructor-instance-constructor.html