C#靜態類,靜態構造函數,靜態變量

靜態變量位於棧上,它是一個全局變量,在編譯期就已經生成。dom

    public class Cow 
        public static int count; 
        private int id; 
        {
            id = ++count;
    }

 

客戶端建立2個Cow的實例,並打印靜態變量count。函數

        static void Main(string[] args) 
            Console.WriteLine(Cow.count);
            Cow cow1 = new Cow();
            Cow cow2 = new Cow();
            Console.WriteLine(Cow.count);
        }

結果:
0
2
spa

○ 在建立Cow實例以前,全局就已經有了count這個靜態變量
○ 若是在static以前用private修飾,就不能夠經過"類名.靜態字段名"來訪問靜態字段,但全局的靜態字段始終存在
日誌

 

在堆和棧上的表現,以下圖:   blog

14

 

  靜態構造函數get

在Cow類中添加一個靜態構造函數。string

    public class Cow 
        public static int count; 
        private int id; 
        {
            id = ++count;
        static Cow()
            count = new Random().Next(100);
    }

 

在構造函數和靜態構造函數中,都對Cow的靜態字段賦值。如今咱們想了解靜態構造函數在何時觸發。是在用構造函數建立實例的時候觸發嗎?會不會在設置Cow的字段或屬性值的時候觸發?在客戶端,經過打印靜態字段count的值來了解靜態構造函數何時被觸發。it

        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實例的時候,靜態構造函數沒有被觸發,而是經過構造函數建立實例
○ 靜態構造函數只執行一次
編譯

 

由此,咱們是否能夠這樣定論:靜態構造函數是在建立第一個實例時候被觸發的?class

 

橫當作嶺側成峯,來換個角度思考這個問題。在爲類的字段賦值時,會不會觸發靜態構造函數呢?

 

把Cow類修改成:

    public class Cow 
        public static int count; 
        private int id; 
        public static int whatever; 
        {
            id = ++count;
        static Cow()
            count = new Random().Next(100);
            whatever = count + 10;
            Console.WriteLine("靜態構造函數被觸發後count爲:" + Cow.count);
            Console.WriteLine("靜態構造函數被觸發後whatever爲:" + Cow.whatever);
    }


客戶端修改成:

        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實例,靜態構造函數不會被再次觸發
○ 靜態構造函數只執行一次

 

到這裏,關於靜態構造函數被觸發的時機,咱們能夠這樣下結論:不管是經過構造函數建立實例,仍是給類的字段或屬性賦值,靜態構造函數是在全部這些動做以前被觸發的。

 

  靜態類

首先建立一個類,包括靜態成員和非靜態成員。

    public class Logger 
        private static int logNumber = 0; 
        {
            Console.WriteLine("日誌初始化");
        static public void CloseLog() 
            Console.WriteLine("日誌關閉");
        static public void LogMsg(string msg) 
            Console.WriteLine("日誌編號爲:" + logNumber + ":" + msg); 
        public void DoSth() 
            Console.WriteLine("我不是靜態方法~~");
    }

 

在客戶端,既能夠經過"類名.靜態方法名稱"調用方法,也能夠經過類的實例調用方法。

        static void Main(string[] args) 
            Logger.InitializeLogging();
            Logger.LogMsg("日誌被記錄下了~~");
            Logger.CloseLog();
            Logger logger = new Logger();
            logger.DoSth();
        }

 

若是把一個類設置成靜態類,意味着:這個類的全部一切存在於棧上,所以該類中不能有實例方法,也不能建立該類實例。

 

修改Logger類,把實例方法去掉。

    public static class Logger 
        private static int logNumber = 0; 
        {
            Console.WriteLine("日誌初始化");
        static public void CloseLog() 
            Console.WriteLine("日誌關閉");
        static public void LogMsg(string msg) 
            Console.WriteLine("日誌編號爲:" + logNumber + ":" + msg); 
    }

 

在客戶端,更不能建立Logger的實例,只能經過"類名.靜態方法名"調用方法。

        static void Main(string[] args) 
            Logger.InitializeLogging();
            Logger.LogMsg("日誌被記錄下了~~");
            Logger.CloseLog();
        }

 

 

總結:○ 靜態變量屬於全局,位於棧上○ 靜態構造函數只被觸發一次,不管是經過構造函數建立實例,仍是給類的字段或屬性賦值,靜態構造函數的觸發時機都在這些動做以前○ 靜態類中不能有實例成員

相關文章
相關標籤/搜索