[C#] static筆記

  • 2920
  • 0

一直以來對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