靜態類別和靜態類別成員 (C# 程式設計手冊)Static Classes and Static Class Members (C# Programming Guide)

static 類別基本上與非靜態類別相同,但有一項差異︰無法具現化靜態類別。A static class is basically the same as a non-static class, but there is one difference: a static class cannot be instantiated. 換句話說,您不能使用 new 運算子來建立類別型別的變數。In other words, you cannot use the new operator to create a variable of the class type. 因為沒有任何執行個體變數,所以您可以使用類別名稱本身來存取靜態類別的成員。Because there is no instance variable, you access the members of a static class by using the class name itself. 例如,如果您的 UtilityClass 靜態類別包含 MethodA 公用靜態方法,則會呼叫方法,如下列範例所示︰For example, if you have a static class that is named UtilityClass that has a public static method named MethodA, you call the method as shown in the following example:

UtilityClass.MethodA();  

如果方法集只作業於輸入參數,並且不需要取得或設定任何內部執行個體欄位,則靜態類別可以用作其方便使用的容器。A static class can be used as a convenient container for sets of methods that just operate on input parameters and do not have to get or set any internal instance fields. 例如,在 .NET Framework 類別庫中,靜態 System.Math 類別包含可執行數學運算的方法,而不需要儲存或擷取特定 Math 類別執行個體所獨有的資料。For example, in the .NET Framework Class Library, the static System.Math class contains methods that perform mathematical operations, without any requirement to store or retrieve data that is unique to a particular instance of the Math class. 亦即,您可以指定類別名稱和方法名稱來套用類別的成員,如下列範例所示。That is, you apply the members of the class by specifying the class name and the method name, as shown in the following example.

double dub = -3.14;  
Console.WriteLine(Math.Abs(dub));  
Console.WriteLine(Math.Floor(dub));  
Console.WriteLine(Math.Round(Math.Abs(dub)));  
  
// Output:  
// 3.14  
// -4  
// 3  

與所有類別型別的情況相同,載入可參考類別的程式時,.NET Framework Common Language Runtime (CLR) 會載入靜態類別的型別資訊。As is the case with all class types, the type information for a static class is loaded by the .NET Framework common language runtime (CLR) when the program that references the class is loaded. 程式無法指定確實載入類別的時間。The program cannot specify exactly when the class is loaded. 不過,一定會載入類別、初始化其欄位,並在第一次於程式中參考類別之前呼叫其靜態建構函式。However, it is guaranteed to be loaded and to have its fields initialized and its static constructor called before the class is referenced for the first time in your program. 只會呼叫靜態建構函式一次,而且靜態類別在程式所在應用程式定義域的存留期間保留在記憶體中。A static constructor is only called one time, and a static class remains in memory for the lifetime of the application domain in which your program resides.

注意

若要建立只允許建立它本身之一個執行個體的非靜態類別,請參閱 Implementing Singleton in C# (在 C# 中實作單一)。To create a non-static class that allows only one instance of itself to be created, see Implementing Singleton in C#.

下列清單提供靜態類別的主要功能︰The following list provides the main features of a static class:

因此,建立靜態類別,基本上與建立只包含靜態成員和私用建構函式的類別相同。Creating a static class is therefore basically the same as creating a class that contains only static members and a private constructor. 私用建構函式可防止具現化類別。A private constructor prevents the class from being instantiated. 使用靜態類別的優點在於編譯器可以確認不會意外新增任何執行個體成員。The advantage of using a static class is that the compiler can check to make sure that no instance members are accidentally added. 編譯器將保證無法建立此類別的執行個體。The compiler will guarantee that instances of this class cannot be created.

靜態類別已密封,因此無法進行繼承。Static classes are sealed and therefore cannot be inherited. 它們無法繼承自 Object 以外的任何類別。They cannot inherit from any class except Object. 靜態類別不能包含執行個體建構函式,但可以包含靜態建構函式。Static classes cannot contain an instance constructor; however, they can contain a static constructor. 如果類別包含需要重要初始化的靜態成員,則非靜態類別也應該定義靜態建構函式。Non-static classes should also define a static constructor if the class contains static members that require non-trivial initialization. 如需詳細資訊,請參閱靜態建構函式For more information, see Static Constructors.

範例Example

以下是包含兩種方法可將溫度從攝氏轉換為華氏以及從華氏轉換為攝氏的靜態類別範例︰Here is an example of a static class that contains two methods that convert temperature from Celsius to Fahrenheit and from Fahrenheit to Celsius:

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 Members

非靜態類別可以包含靜態方法、欄位、屬性或事件。A non-static class can contain static methods, fields, properties, or events. 即使尚未建立類別的執行個體,還是可以在類別上呼叫靜態成員。The static member is callable on a class even when no instance of the class has been created. 靜態成員一律是透過類別名稱進行存取,而不是執行個體名稱。The static member is always accessed by the class name, not the instance name. 不論建立多少個類別執行個體,都只會有一個靜態成員複本。Only one copy of a static member exists, regardless of how many instances of the class are created. 靜態方法和屬性無法存取其包含類型中的非靜態欄位和事件,也無法存取任何物件的執行個體變數,除非它明確地傳入方法參數。Static methods and properties cannot access non-static fields and events in their containing type, and they cannot access an instance variable of any object unless it is explicitly passed in a method parameter.

使用一些靜態成員宣告非靜態類別,會比將整個類別宣告為靜態更為常見。It is more typical to declare a non-static class with some static members, than to declare an entire class as static. 靜態欄位的兩個常用用法是持續計算已具現化的物件數目,或是儲存必須在所有執行個體之間共用的值。Two common uses of static fields are to keep a count of the number of objects that have been instantiated, or to store a value that must be shared among all instances.

可以多載但無法覆寫靜態方法,因為它們屬於類別,而不是類別的任何執行個體。Static methods can be overloaded but not overridden, because they belong to the class, and not to any instance of the class.

雖然欄位不可以宣告為 static const,但是 const 欄位在其行為中基本上是靜態的。Although a field cannot be declared as static const, a const field is essentially static in its behavior. 它屬於類型,而不是類型的執行個體。It belongs to the type, not to instances of the type. 因此,使用用於靜態欄位的相同 ClassName.MemberName 標記法可以存取 const 欄位。Therefore, const fields can be accessed by using the same ClassName.MemberName notation that is used for static fields. 不需要物件執行個體。No object instance is required.

C# 不支援靜態區域變數 (方法範圍中所宣告的變數)。C# does not support static local variables (variables that are declared in method scope).

在成員的傳回型別前面使用 static 關鍵字,即可宣告靜態類別成員,如下列範例所示︰You declare static class members by using the static keyword before the return type of the member, as shown in the following example:

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...
}

第一次存取靜態成員之前,以及呼叫靜態建構函式 (如果有的話) 之前,都會初始化靜態成員。Static members are initialized before the static member is accessed for the first time and before the static constructor, if there is one, is called. 若要存取靜態類別成員,請使用類別的名稱來指定成員的位置,而不是變數名稱,如下列範例所示︰To access a static class member, use the name of the class instead of a variable name to specify the location of the member, as shown in the following example:

Automobile.Drive();
int i = Automobile.NumberOfWheels;

如果您的類別包含靜態欄位,請提供在載入類別時初始化它們的靜態建構函式。If your class contains static fields, provide a static constructor that initializes them when the class is loaded.

靜態方法的呼叫會使用 Microsoft Intermediate Language (MSIL) 產生呼叫指令,而執行個體方法的呼叫會產生 callvirt 指令,這也會檢查是否有 Null 物件參考。A call to a static method generates a call instruction in Microsoft intermediate language (MSIL), whereas a call to an instance method generates a callvirt instruction, which also checks for a null object references. 不過,大部分的時間,兩者之間的效能差異並不明顯。However, most of the time the performance difference between the two is not significant.

C# 語言規格C# Language Specification

如需詳細資訊,請參閱 C# 語言規格中的靜態類別靜態和執行個體的成員For more information, see Static classes and Static and instance members in the C# Language Specification. 語言規格是 C# 語法及用法的限定來源。The language specification is the definitive source for C# syntax and usage.

另請參閱See also