靜態類別和靜態類別成員 (C# 程式設計手冊)

更新: 2008 年 7 月

靜態類別基本上跟非靜態類別相同,但有一個差別:靜態類別不能具現化 (Instantiated)。換句話說,您不能使用 new 關鍵字建立類別型別的變數。由於沒有執行個體變數,您要使用類別名稱本身存取靜態類別的成員。例如,如果您有稱為 UtilityClass 的靜態類別,其中有稱為 MethodA 的公用方法,您必須如下列範例所示呼叫方法:

UtilityClass.MethodA();

跟所有類別型別一樣,靜態類別的型別資訊,是由 .NET Framework Common Language Runtime (CLR) 在載入參考該類別的程式時載入。程式無法確實指定何時載入類別。然而,類別卻能保證一定會載入,並會在您的程式第一次參考此類別前,先讓其中的欄位初始化,而其中的靜態建構函式也受到呼叫。靜態建構函式只會受到一次呼叫,而後在您程式所在的應用程式定義域的存留期 (Lifetime) 中,都會在記憶體中保留靜態類別。

靜態類別能供只在輸入參數上作業,且不需要取得或設定任何內部執行個體欄位的方法集,做為方便的容器。例如,在 .NET Framework 類別庫中,靜態 System.Math 類別包含幾項執行算術運算的方法,而完全不需要儲存或擷取 Math 類別之特定執行個體的唯一性資料。

注意事項:

若要建立一個非靜態類別,僅允許為其本身建立一個執行個體,請參閱在 C# 中實作單一類別 (英文)。

下列清單會提供靜態類別的主要特色:

因此基本上,建立靜態類別就是建立只包含靜態成員和私用建構函式 (Private Constructor) 的類別。私用建構函式可讓類別避免執行個體化。使用靜態類別的好處是,編譯器可進行檢查,確定不會在不小心的情況下加入執行個體成員。編譯器將可確保這個類別不會建立執行個體。

靜態類別是密封的,因此無法繼承。它們不能繼承自 Object 以外的任何類別。靜態類別不能包含執行個體建構函式。不過,它們可以包含靜態建構函式。非靜態類別如果包含需要非一般初始化的靜態成員,則也應該定義靜態建構函式。如需詳細資訊,請參閱靜態建構函式 (C# 程式設計手冊)

範例

下面是靜態類別的範例,該類別包含可來回換算攝氏溫度與華氏溫度的兩個方法:

public static class TemperatureConverter
{
    public static double CelsiusToFahrenheit(string temperatureCelsius)
    {
        // Convert argument to double for calculations.
        double celsius = Double.Parse(temperatureCelsius);

        // Convert Celsius to Fahrenheit.
        double fahrenheit = (celsius * 9 / 5) + 32;

        return fahrenheit;
    }

    public static double FahrenheitToCelsius(string temperatureFahrenheit)
    {
        // Convert argument to double for calculations.
        double fahrenheit = Double.Parse(temperatureFahrenheit);

        // Convert Fahrenheit to Celsius.
        double celsius = (fahrenheit - 32) * 5 / 9;

        return celsius;
    }
}

class TestTemperatureConverter
{
    static void Main()
    {
        Console.WriteLine("Please select the convertor direction");
        Console.WriteLine("1. From Celsius to Fahrenheit.");
        Console.WriteLine("2. From Fahrenheit to Celsius.");
        Console.Write(":");

        string selection = Console.ReadLine();
        double F, C = 0;

        switch (selection)
        {
            case "1":
                Console.Write("Please enter the Celsius temperature: ");
                F = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine());
                Console.WriteLine("Temperature in Fahrenheit: {0:F2}", F);
                break;

            case "2":
                Console.Write("Please enter the Fahrenheit temperature: ");
                C = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine());
                Console.WriteLine("Temperature in Celsius: {0:F2}", C);
                break;

            default:
                Console.WriteLine("Please select a convertor.");
                break;
        }

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Example Output:
    Please select the convertor direction
    1. From Celsius to Fahrenheit.
    2. From Fahrenheit to Celsius.
    :2
    Please enter the Fahrenheit temperature: 20
    Temperature in Celsius: -6.67
    Press any key to exit.
 */

靜態成員

非靜態類別能包含靜態方法、欄位、屬性或事件。即使沒有建立類別的任何執行個體,還是可以在類別上呼叫靜態成員。靜態成員永遠以類別名稱存取,而不以執行個體名稱存取。不管一個類別建立多少個執行個體,還是只能有一個靜態成員的複本存在。除非明確傳遞了方法參數,否則靜態方法和屬性不能在包含的型別中存取非靜態欄位與事件,也不能存取任何物件的執行個體變數。

比起將整個類別宣告為靜態,以一些靜態成員宣告非靜態類別是較典型的方法。靜態欄位有兩個常見的作用,分別是計算已具現化的物件數,或儲存必須在所有執行個體間共用的值。

靜態方法由於屬於類別而不屬於類別的任何執行個體,因此能多載但不能覆寫。

雖然欄位不能宣告為 static const,const 欄位的行為基本上是靜態的,屬於型別,而非型別的執行個體。因此,const 欄位可透過用於靜態欄位的相同 ClassName.MemberName 標記法存取,不需要任何物件執行個體。

C# 不支援靜態區域變數 (在方法範圍中宣告的變數)。

您要使用 static 關鍵字,在成員的傳回型別前宣告靜態類別成員,如下列範例所示:

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;

如果您的類別包含靜態欄位,請提供在類別載入時會將其初始化的靜態建構函式。

對靜態方法的呼叫會在 Microsoft Intermediate Language (MSIL) 中產生呼叫指令,同時對執行個體方法的呼叫會產生 callvirt 指令,並會檢查 null 物件參考。然而在大部分情況中,這兩者之間的效能差異並不顯著。

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格中的下列章節:

  • 10.1.1.3 靜態類別

請參閱

概念

C# 程式設計手冊

靜態類別設計

參考

類別 (C# 程式設計手冊)

類別 (C# 參考)

靜態建構函式 (C# 程式設計手冊)

執行個體建構函式 (C# 程式設計手冊)

變更記錄

日期

記錄

原因

2008 年 7 月

加入內容與程式碼範例。

資訊加強。