靜態變量
靜態變量位于棧上,它是一個全局變量,在編譯期就已經生成。
1
2
3
4
5
6
7
8
9
|
public class Cow { public static int count; private int id; public Cow() { id = ++count; } } |
客戶端創建2個Cow的實例,并打印靜態變量count。
1
2
3
4
5
6
7
|
static void Main( string [] args) { Console.WriteLine(Cow.count); Cow cow1 = new Cow(); Cow cow2 = new Cow(); Console.WriteLine(Cow.count); } |
結果:
0
2
○ 在創建Cow實例之前,全局就已經有了count這個靜態變量
○ 如果在static之前用private修飾,就不可以通過"類名.靜態字段名"來訪問靜態字段,但全局的靜態字段始終存在
在堆和棧上的表現,如下圖:
靜態構造函數
在Cow類中添加一個靜態構造函數。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Cow { public static int count; private int id; public Cow() { id = ++count; } static Cow() { count = new Random().Next(100); } } |
在構造函數和靜態構造函數中,都對Cow的靜態字段賦值。現在我們想了解靜態構造函數在什么時候觸發。是在用構造函數創建實例的時候觸發嗎?會不會在設置Cow的字段或屬性值的時候觸發?在客戶端,通過打印靜態字段count的值來了解靜態構造函數什么時候被觸發。
1
|
static void Main( string [] args) { Cow cow1 = new Cow(); Console.WriteLine( "創建第一個Cow實例后count為:" + Cow.count); Cow cow2 = new Cow(); Console.WriteLine( "創建第二個Cow實例后count為:" + Cow.count); } |
○ 靜態構造函數在創建第一個Cow實例的時候被觸發
○ 在創建第二個Cow實例的時候,靜態構造函數沒有被觸發,而是通過構造函數創建實例
○ 靜態構造函數只執行一次
由此,我們是否可以這樣定論:靜態構造函數是在創建第一個實例時候被觸發的?
橫看成嶺側成峰,來換個角度思考這個問題。在為類的字段賦值時,會不會觸發靜態構造函數呢?
把Cow類修改為:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class Cow { public static int count; private int id; public static int whatever; public Cow() { id = ++count; } static Cow() { count = new Random().Next(100); whatever = count + 10; Console.WriteLine( "靜態構造函數被觸發后count為:" + Cow.count); Console.WriteLine( "靜態構造函數被觸發后whatever為:" + Cow.whatever); } } |
客戶端修改為:
1
2
3
4
5
6
7
8
|
static void Main( string [] args) { Cow.count = 100; Cow cow1 = new Cow(); Console.WriteLine( "創建第一個Cow實例后count為:" + Cow.count); Cow cow2 = new Cow(); Console.WriteLine( "創建第二個Cow實例后count為:" + Cow.count); } |
○ 在為Cow的字段賦值之前,靜態構造函數被觸發
○ 接著創建Cow實例,靜態構造函數不會被再次觸發
○ 靜態構造函數只執行一次
到這里,關于靜態構造函數被觸發的時機,我們可以這樣下結論:無論是通過構造函數創建實例,還是給類的字段或屬性賦值,靜態構造函數是在所有這些動作之前被觸發的。
靜態類
首先創建一個類,包括靜態成員和非靜態成員。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public class Logger { private static int logNumber = 0; static public void InitializeLogging() { Console.WriteLine( "日志初始化" ); } static public void CloseLog() { Console.WriteLine( "日志關閉" ); } static public void LogMsg( string msg) { Console.WriteLine( "日志編號為:" + logNumber + ":" + msg); } public void DoSth() { Console.WriteLine( "我不是靜態方法~~" ); } } |
在客戶端,既可以通過"類名.靜態方法名稱"調用方法,也可以通過類的實例調用方法。
1
2
3
4
5
6
7
8
|
static void Main( string [] args) { Logger.InitializeLogging(); Logger.LogMsg( "日志被記錄下了~~" ); Logger.CloseLog(); Logger logger = new Logger(); logger.DoSth(); } |
如果把一個類設置成靜態類,意味著:這個類的所有一切存在于棧上,因此該類中不能有實例方法,也不能創建該類實例。
修改Logger類,把實例方法去掉。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public static class Logger { private static int logNumber = 0; static public void InitializeLogging() { Console.WriteLine( "日志初始化" ); } static public void CloseLog() { Console.WriteLine( "日志關閉" ); } static public void LogMsg( string msg) { Console.WriteLine( "日志編號為:" + logNumber + ":" + msg); } } |
在客戶端,更不能創建Logger的實例,只能通過"類名.靜態方法名"調用方法。
1
2
3
4
5
6
|
static void Main( string [] args) { Logger.InitializeLogging(); Logger.LogMsg( "日志被記錄下了~~" ); Logger.CloseLog(); } |
總結:
○ 靜態變量屬于全局,位于棧上
○ 靜態構造函數只被觸發一次,無論是通過構造函數創建實例,還是給類的字段或屬性賦值,靜態構造函數的觸發時機都在這些動作之前
○ 靜態類中不能有實例成員
以上內容是小編給大家介紹的C#靜態類,靜態構造函數,靜態變量的全部敘述,希望對大家有所幫助!