靜態類別基本上與非靜態類別相同,但有一個差異:無法具現化靜態類別。 換句話說,您無法使用 新的 運算符來建立類別類型的變數。 因為沒有實例變數,因此您可以使用類別名稱本身來存取靜態類別的成員。 例如,如果您有名為 UtilityClass
的靜態類別具有名為 MethodA
的公用靜態方法,您可以呼叫 方法,如下列範例所示:
UtilityClass.MethodA();
靜態類別可用來作為一組方便的容器,這些方法只會在輸入參數上運作,而且不需要取得或設定任何內部實例字段。 例如,在 .NET 類別庫中,靜態 System.Math 類別包含執行數學運算的方法,而不需要儲存或擷取類別特定實例 Math 特有的數據。 也就是說,您可以藉由指定類別名稱和方法名稱來套用 類別的成員,如下列範例所示。
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 運行時間會載入靜態類別的類型資訊。 程式無法確切地指定載入類別的時機。 不過,它保證會在程式中第一次參考 類別之前,載入並初始化其字段,並呼叫其靜態建構函式。 靜態建構函式只會呼叫一次,而靜態類別會在您程式所在的應用程式域存留期內保留在記憶體中。
備註
若要建立只允許建立一個本身實例的非靜態類別,請參閱 在 C# 中實作 Singleton。
下列清單提供靜態類別的主要功能:
只包含靜態成員。
無法具現化。
是密封的。
不能包含 實例建構函式。
因此,建立靜態類別基本上與建立只包含靜態成員和私用建構函式的類別相同。 私人建構函式可防止類別具現化。 使用靜態類別的優點是編譯程式可以檢查以確定不會意外新增任何實例成員。 編譯程式保證無法建立這個類別的實例。
靜態類別是密封的,因此無法繼承。 除了 Object之外,它們無法繼承自任何類別或介面。 靜態類別不能包含實例建構函式。 不過,它們可以包含靜態建構函式。 如果類別包含需要非簡單初始化的靜態成員,非靜態類別也應該定義靜態建構函式。 如需詳細資訊,請參閱 靜態建構函式。
範例
以下是靜態類別的範例,其中包含兩種方法,可將溫度從攝氏轉換為華氏,以及從華氏轉換為攝氏:
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() ?? "0");
Console.WriteLine($"Temperature in Fahrenheit: {F:F2}");
break;
case "2":
Console.Write("Please enter the Fahrenheit temperature: ");
C = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine() ?? "0");
Console.WriteLine($"Temperature in Celsius: {C:F2}");
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;
如果您的類別包含靜態字段,請提供靜態建構函式,以在載入類別時初始化它們。
對靜態方法的呼叫會以通用中繼語言 (CIL) 產生呼叫指令,而實例方法的呼叫會產生 callvirt
指令,這也會檢查 Null 物件參考。 不過,在大部分情況下,兩者之間的效能差異並不重要。
C# 語言規格
如需詳細資訊,請參閱 C# 語言規格中的靜態類別、靜態和實例成員和靜態建構函式。 語言規格是 C# 語法和使用方式的最終來源。