靜態成員以 static 關鍵字對其進行宣告,此種類型的成員不需類別實體,直接透過類別名稱以點 . 運算子連接成員名稱進行引用,以下為靜態成員的宣告語法:
其中 static 宣告為靜態成員的關鍵字,而 T 為成員型態, Smember 則是成員命名,例如變數或是方法,一旦以 static 宣告,直接透過類別名稱進行引用即可。
靜態成員最好的例子,是用來作為程式起始點的 Main 方法,在每個新建立的主控台應用程式專案中,會自動產生這個主方法,以 static 關鍵字進行宣告:
由於應用程式是在沒有任何物件被建立的情形下開始,這個方法被宣告為 static ,不需要實體即可執行,啟動應用程式。
以下的 TimeConversion 類別示範靜態成員。
欄位 hour 代表一天的小時數, min 則代表一小時的分鐘數,這兩個都是固定的數值,以 static 直接宣告為靜態。
接下來的HourToMin 函式與 DayToHour 函式,同樣均是 static ,分別執行小時/分鐘數的轉換與日/時數的轉換。 HourToMin 函式將參數值 pHour 乘上 min ,代表由時數轉為分鐘數, DayToHour 函數則將參數 pDay 乘上 hour ,代表從天數轉換成為小時數。
主程式方法 Main 的引用 TimeConversion 類別所定義的靜態方法,由於是靜態成員,因此並不需要建立 TimeConversion 物件。
由於時間單位的換算邏輯是固定的,對於這些固定的值或運算邏輯,設計為靜態成員是比更合適的選擇,透過相同的類別即可取得需要的結果,反過來說,靜態成員並不會隨著物件的建立而有不同的值,所有類別的靜態成員均是同一個版本,只有不隨物件實體改變的固定資料成員,才需要考慮建立靜態成員,否則實體成員才是正確的選擇。
另外要特別注意,一旦宣告為靜態,其中引用的同樣必須是靜態成員:
將其中的欄位,包含 hour 與 min 移除 static 關鍵字宣告,重新執行會出現以下的錯誤訊息:
無論 HourToMin() 或是 DayToHour() ,都是 static ,因此都會出現以上的錯誤訊息。
靜態建構式
在類別物件建立的過程中,如果需要初始化靜態變數,可以透過定義靜態建構式來提供需要的支援,在建構式名稱之前標註 static 即可成為靜態建構式。
在這個類別中,變數 now 是靜態的唯讀欄位,於宣告為 static的建構式中將其初始化為建構式執行當下的時間,而為了方便測試說明,最後將其輸出。
靜態建構式在第一次物件建立時被執行,而且僅執行一次,以下嘗試建立兩個 StaticConstructors 物件。
當這兩行程式碼執行完畢,會得到以下的輸出結果:
變數值 now 只經過一次設定並輸出,也就是第一次物件 sc0 建立的時候,接下來建立StaticConstructors 物件 sc1 ,將不會再執行靜態建構式。
另外,如果未建立任何實體物件,而第一次引用靜態成員時,同樣會執行靜態建構式,例如以下這一行程式碼:
其中引用了靜態變數 now 取得其值,此時靜態建構式執行,輸出當下的時間。
關於常數 constant
如果類別有宣告為常數(const)的成員,本身即具備靜態特性,不需要再宣告為 static ,直接透過類別名稱進行引用即可。
欄位 boiling_point 與 freezing_point 分別表示水的沸點與冰點(攝氏),由於是固定值因此宣告為const ,接下來嘗試讀取欄位值:
其中透過類別名稱,直接引用 const 欄位值,並將取得的值輸出。
輸出結果中,可以看到引用 const 欄位的效果。事實上,將一個 const 成員宣告為 static 是不合法的,你不可以宣告如下:
其中的 static 會導以下的錯誤訊息:
靜態類別
類別本身亦能直接宣告為靜態,當類別之中沒有資料或是方法成員與類別實體有任何關聯,直接建立靜態類別可以將類別成員與物件的運作完全獨立開來,這特別適合我們用來建立提供整個應用程式所需的公用成員類別。
建立靜態類需以關鍵字static對類別進行宣告:
經過 static 修飾, StaticClass 便成為一個靜態類別,設計這個類別的時候必須遵守上述的限制。
SecondConversion 類別宣告為靜態,這是一個轉換時間秒數的類別程式,其中定義了三個靜態方法成員,分別將指定的日、小時與分鐘數,轉換成為對等的秒數回傳。
由於轉換的公式為不變的常理,即使在任何情況下這種規則依然不會改變,因此它們不需要與任何類別實體產生關聯,宣告為 static 可以避免在執行階段產生任何不必要的類別實體。
一開始直接透過類別名稱SecondConversion 引用靜態成員,取得轉換後的結果輸出。
設計靜態類別有幾點必須注意,除了只能配置靜態成員,另外本身無法建立其實體物件,例如以下這一行程式碼:
其中會產生以下的錯誤訊息:
.NET 內建的 Math 類別,是一個最典型的靜態類別,進入 Math 類別的規格頁可以看到這個類別的宣告如下:
由於數算運算方法公式均是固定的,例如計算絕對值的 abs() ,或是三角函式的 sin()、cos() 以及 Tan() 等等,因此 Math 類別直接設計成靜態類別可以更方便使用。
static T Smember
其中 static 宣告為靜態成員的關鍵字,而 T 為成員型態, Smember 則是成員命名,例如變數或是方法,一旦以 static 宣告,直接透過類別名稱進行引用即可。
靜態成員最好的例子,是用來作為程式起始點的 Main 方法,在每個新建立的主控台應用程式專案中,會自動產生這個主方法,以 static 關鍵字進行宣告:
static void Main(string[] args)
{
}
{
}
由於應用程式是在沒有任何物件被建立的情形下開始,這個方法被宣告為 static ,不需要實體即可執行,啟動應用程式。
以下的 TimeConversion 類別示範靜態成員。
class TimeConversion
{
private static int hour = 24;
private static int min = 60;
public static int HourToMin(int pHour)
{
int intMin;
intMin = pHour * min;
return intMin;
}
public static int DayToHour(int pDay)
{
int intHour;
intHour = pDay * hour;
return intHour;
}
}
{
private static int hour = 24;
private static int min = 60;
public static int HourToMin(int pHour)
{
int intMin;
intMin = pHour * min;
return intMin;
}
public static int DayToHour(int pDay)
{
int intHour;
intHour = pDay * hour;
return intHour;
}
}
欄位 hour 代表一天的小時數, min 則代表一小時的分鐘數,這兩個都是固定的數值,以 static 直接宣告為靜態。
接下來的HourToMin 函式與 DayToHour 函式,同樣均是 static ,分別執行小時/分鐘數的轉換與日/時數的轉換。 HourToMin 函式將參數值 pHour 乘上 min ,代表由時數轉為分鐘數, DayToHour 函數則將參數 pDay 乘上 hour ,代表從天數轉換成為小時數。
class Program
{
static void Main(string[] args)
{
int hour;
int day;
int min;
int ahour;
Console.Write("請輸入小時數:");
hour = int.Parse(Console.ReadLine());
Console.Write("請輸入天數:");
day = int.Parse(Console.ReadLine());
min = TimeConversion.HourToMin(hour);
ahour = TimeConversion.DayToHour(day);
Console.WriteLine("");
Console.WriteLine("{0} 個小時等於 {1} 分鐘!!", hour, min);
Console.WriteLine("{0} 天等於 {1} 個小時!!", day, ahour);
Console.ReadKey();
}
}
{
static void Main(string[] args)
{
int hour;
int day;
int min;
int ahour;
Console.Write("請輸入小時數:");
hour = int.Parse(Console.ReadLine());
Console.Write("請輸入天數:");
day = int.Parse(Console.ReadLine());
min = TimeConversion.HourToMin(hour);
ahour = TimeConversion.DayToHour(day);
Console.WriteLine("");
Console.WriteLine("{0} 個小時等於 {1} 分鐘!!", hour, min);
Console.WriteLine("{0} 天等於 {1} 個小時!!", day, ahour);
Console.ReadKey();
}
}
主程式方法 Main 的引用 TimeConversion 類別所定義的靜態方法,由於是靜態成員,因此並不需要建立 TimeConversion 物件。
請輸入小時數:6
請輸入天數:4
6 個小時等於 360 分鐘
4 天等於 96 個小時
請輸入天數:4
6 個小時等於 360 分鐘
4 天等於 96 個小時
由於時間單位的換算邏輯是固定的,對於這些固定的值或運算邏輯,設計為靜態成員是比更合適的選擇,透過相同的類別即可取得需要的結果,反過來說,靜態成員並不會隨著物件的建立而有不同的值,所有類別的靜態成員均是同一個版本,只有不隨物件實體改變的固定資料成員,才需要考慮建立靜態成員,否則實體成員才是正確的選擇。
另外要特別注意,一旦宣告為靜態,其中引用的同樣必須是靜態成員:
class TimeConversion
{
private int hour = 24;
private int min = 60;
public static int HourToMin(int pHour)
{
int intMin;
intMin = pHour * min;
return intMin;
}
public static int DayToHour(int pDay)
{
int intHour;
intHour = pDay * hour;
return intHour;
}
}
{
private int hour = 24;
private int min = 60;
public static int HourToMin(int pHour)
{
int intMin;
intMin = pHour * min;
return intMin;
}
public static int DayToHour(int pDay)
{
int intHour;
intHour = pDay * hour;
return intHour;
}
}
將其中的欄位,包含 hour 與 min 移除 static 關鍵字宣告,重新執行會出現以下的錯誤訊息:
錯誤 CS0120 需要有物件參考,才可使用非靜態欄位、方法或屬性 'TimeConversion.hour'。
錯誤 CS0120 需要有物件參考,才可使用非靜態欄位、方法或屬性 'TimeConversion.min'。
錯誤 CS0120 需要有物件參考,才可使用非靜態欄位、方法或屬性 'TimeConversion.min'。
無論 HourToMin() 或是 DayToHour() ,都是 static ,因此都會出現以上的錯誤訊息。
靜態建構式
在類別物件建立的過程中,如果需要初始化靜態變數,可以透過定義靜態建構式來提供需要的支援,在建構式名稱之前標註 static 即可成為靜態建構式。
public class StaticConstructors
{
public static readonly string now;
static Static Constructors()
{
now = DateTime.Now.ToString();
Console.WriteLine("Now:{0}", now);
}
}
{
public static readonly string now;
static Static Constructors()
{
now = DateTime.Now.ToString();
Console.WriteLine("Now:{0}", now);
}
}
在這個類別中,變數 now 是靜態的唯讀欄位,於宣告為 static的建構式中將其初始化為建構式執行當下的時間,而為了方便測試說明,最後將其輸出。
靜態建構式在第一次物件建立時被執行,而且僅執行一次,以下嘗試建立兩個 StaticConstructors 物件。
StaticConstructors sc0 = new StaticConstructors();
StaticConstructors sc1 = new StaticConstructors();
StaticConstructors sc1 = new StaticConstructors();
當這兩行程式碼執行完畢,會得到以下的輸出結果:
Now:2018/2/13 下午 04:36:03
變數值 now 只經過一次設定並輸出,也就是第一次物件 sc0 建立的時候,接下來建立StaticConstructors 物件 sc1 ,將不會再執行靜態建構式。
另外,如果未建立任何實體物件,而第一次引用靜態成員時,同樣會執行靜態建構式,例如以下這一行程式碼:
string now = StaticConstructors.now;
其中引用了靜態變數 now 取得其值,此時靜態建構式執行,輸出當下的時間。
關於常數 constant
如果類別有宣告為常數(const)的成員,本身即具備靜態特性,不需要再宣告為 static ,直接透過類別名稱進行引用即可。
public class TemperatureConversion
{
public const double boiling_point = 100.0;
public const double freezing_point = 0.0;
}
{
public const double boiling_point = 100.0;
public const double freezing_point = 0.0;
}
欄位 boiling_point 與 freezing_point 分別表示水的沸點與冰點(攝氏),由於是固定值因此宣告為const ,接下來嘗試讀取欄位值:
double bp = TemperatureConversion.boiling_point;
double fp = TemperatureConversion.freezing_point;
Console.WriteLine("水的沸點是攝氏 {0} 度 ", bp);
Console.WriteLine("水的冰點是攝氏 {0} 度 ", fp);
double fp = TemperatureConversion.freezing_point;
Console.WriteLine("水的沸點是攝氏 {0} 度 ", bp);
Console.WriteLine("水的冰點是攝氏 {0} 度 ", fp);
其中透過類別名稱,直接引用 const 欄位值,並將取得的值輸出。
水的沸點是攝氏 100 度
水的冰點是攝氏 0 度
水的冰點是攝氏 0 度
輸出結果中,可以看到引用 const 欄位的效果。事實上,將一個 const 成員宣告為 static 是不合法的,你不可以宣告如下:
public static const double boiling_point = 100.0 ;
其中的 static 會導以下的錯誤訊息:
錯誤 CS0504 常數 'boiling_point' 不可標記為 static
靜態類別
類別本身亦能直接宣告為靜態,當類別之中沒有資料或是方法成員與類別實體有任何關聯,直接建立靜態類別可以將類別成員與物件的運作完全獨立開來,這特別適合我們用來建立提供整個應用程式所需的公用成員類別。
建立靜態類需以關鍵字static對類別進行宣告:
static class StaticClass
{
// 靜態成員 …
}
{
// 靜態成員 …
}
經過 static 修飾, StaticClass 便成為一個靜態類別,設計這個類別的時候必須遵守上述的限制。
static class SecondConversion
{
public static int HourToSecond(int hour)
{
return hour * 60 * 60;
}
public static int DayToSecond(int day)
{
return day * 60 * 60 * 24;
}
public static int MinToSecond(int min)
{
return min * 60;
}
}
{
public static int HourToSecond(int hour)
{
return hour * 60 * 60;
}
public static int DayToSecond(int day)
{
return day * 60 * 60 * 24;
}
public static int MinToSecond(int min)
{
return min * 60;
}
}
SecondConversion 類別宣告為靜態,這是一個轉換時間秒數的類別程式,其中定義了三個靜態方法成員,分別將指定的日、小時與分鐘數,轉換成為對等的秒數回傳。
由於轉換的公式為不變的常理,即使在任何情況下這種規則依然不會改變,因此它們不需要與任何類別實體產生關聯,宣告為 static 可以避免在執行階段產生任何不必要的類別實體。
class Program
{
static void Main(string[] args)
{
int msecond = SecondConversion.MinToSecond(5);
int hsecond = SecondConversion.HourToSecond(5);
int dsecond = SecondConversion.DayToSecond(5);
Console.WriteLine("5分鐘等於 {0} 秒 ", msecond);
Console.WriteLine("5小時等於 {0} 秒 ", hsecond);
Console.WriteLine("5日 等於 {0} 秒 ", dsecond);
Console.ReadLine();
}
}
{
static void Main(string[] args)
{
int msecond = SecondConversion.MinToSecond(5);
int hsecond = SecondConversion.HourToSecond(5);
int dsecond = SecondConversion.DayToSecond(5);
Console.WriteLine("5分鐘等於 {0} 秒 ", msecond);
Console.WriteLine("5小時等於 {0} 秒 ", hsecond);
Console.WriteLine("5日 等於 {0} 秒 ", dsecond);
Console.ReadLine();
}
}
一開始直接透過類別名稱SecondConversion 引用靜態成員,取得轉換後的結果輸出。
5分鐘等於 300 秒
5小時等於 18000 秒
5日 等於 432000 秒
5小時等於 18000 秒
5日 等於 432000 秒
設計靜態類別有幾點必須注意,除了只能配置靜態成員,另外本身無法建立其實體物件,例如以下這一行程式碼:
SecondConversion sc = new SecondConversion();
其中會產生以下的錯誤訊息:
錯誤 CS0723 無法宣告靜態類型 'SecondConversion' 的變數
錯誤 CS0712 無法建立靜態類別 'SecondConversion' 的執行個體
錯誤 CS0712 無法建立靜態類別 'SecondConversion' 的執行個體
.NET 內建的 Math 類別,是一個最典型的靜態類別,進入 Math 類別的規格頁可以看到這個類別的宣告如下:
public static class Math
由於數算運算方法公式均是固定的,例如計算絕對值的 abs() ,或是三角函式的 sin()、cos() 以及 Tan() 等等,因此 Math 類別直接設計成靜態類別可以更方便使用。
沒有留言:
張貼留言