在C#中,靜態和非靜態的特徵對於咱們來講是再熟悉不過了,可是不多看到有一篇文章去好好地總結靜態和非靜態它們之間的不一樣,爲了幫助你們更好地去理解靜態和非靜態特徵, 因此將在這篇文章中幫你們全面總結下它們之間的不一樣,包括靜態類,靜態成員和靜態構造函數。但願在你們鞏固基礎的時候能夠拿出來好好複習下的。下面廢話很少了,直接進入咱們今天的主題。程序員
在自定義類或看.NET Framework類庫中均可以發現,類中大部分都是具體實例特徵(也就是沒有static標識的),同時咱們也能看到一些具備靜態特徵的類或成員,例如咱們常用的Console類以及WriteLine方法就是靜態的。然而有些朋友會疑惑,爲何還要有靜態特徵的呢?乾脆都定義爲實例的好了? 而後靜態特徵的存在確定有它存在的緣由的,並非咱們就是要這麼定義的,其實我一直認爲不論是什麼都是源於生活的, 技術的實現也是同樣,好比咱們開發程序,須要掌握技術外,其實更重要的是業務邏輯這塊的,若是你都不知道你開發的東西是怎樣的一個流程,即便你技術再牛作出來的東西都是反人類的東西(也就是指不符合用戶的用戶習慣和以前的一個業務需求),其實靜態特徵的存在也是源於生活的,對於類比如就是咱們現實生活中的人或事物,靜態特徵和非靜態特徵就比如生活中人或事物具備的特徵, 咱們詢問人的時候或者電視劇警察查案件的時候,都會聽到這樣一句話 "那我的有什麼特徵?"或 「嫌疑犯有什麼特徵?多高,年齡等」 其實高度、年齡、性別都是一我的的特徵,因此這些在語言範疇就須要爲其進行定義了,也就是咱們定義的實例成員了,然而有些特徵須要被全部對象實例所共有的,這些特徵在語言範疇就定義爲靜態特徵,具體哪些特徵能夠定義爲靜態特徵呢? 其實這點同樣是源於生活的,因此咱們在開發軟件的過程當中,必不可少的一個流程就是需求分析了,只有在瞭解客戶需求的條件下才能進行以後的全部流程的, 例如一個班級有不少學生,每一個學生是一個實體,在語言範疇就能夠定義一個類,當咱們須要一個學生的時候就能夠經過new 關鍵字建立一個出來(說到這裏又讓我想到了惡搞泰囧的圖片——你有對象嗎?沒對象,大家程序員能夠本身new一個啊?),然而咱們建立出來的學生他們都有一些共有的特徵,如同一個班級,學校等, 若是咱們把班級、學校這樣的特徵也定義爲實例的話,那麼咱們不是每次建立對象實例的時候都爲這些共有的特徵分配一次內存的,這樣不只對內存空間的浪費也是不知足生活常識的,此時咱們就能夠把班級、學校這樣的特徵定義爲靜態特徵,這樣全部實例均可以共享這兩個特徵,而且不須要爲每一個對象實例分配內存。編程
靜態類和非靜態類在C#中定義基本是同樣的,只是靜態類定義須要加上static修飾符而已。下面就直接總結下它們之間的區別:ide
靜態類只能包含靜態成員,不然會拋出編譯錯誤;然而非靜態類既能夠包含非靜態成員也能夠包含靜態成員函數
靜態類是不能實例化,之因此不能實例化,是由於靜態類會致使C#編譯器將該類同時標記爲abstract和sealed,而且編譯器不會在類型中生成一個實例的構造函數,從而致使靜態類不能實例化,具體緣由能夠見下圖;非靜態類能夠,而且靜態成員的訪問只能經過類來進行訪問,由於靜態成員是屬於類的。工具
publicstaticclass StaticClass { privatestaticstring name; }
上面代碼用IL反彙編程序獲得的IL代碼結構爲:性能
靜態構造函數用來初始化類中的靜態成員的,包括靜態字段和靜態屬性,而且靜態構造函數是不能帶有參數、不能有訪問修飾符,靜態構造函數的調用是由CLR第一次調用類成員以前執行的。this
下面仍是直接總結下靜態構造函數與實例構造函數之間的區別:spa
靜態構造函數能夠與無參的實例構造函數同時存在指針
靜態構造函數在CLR加載類時執行,然而實例構造函數在每次實例建立時都會執行code
靜態構造函數只能對靜態成員初始化,不能對非靜態成員進行初始化操做,然而實例構造函數,既能夠初始化實例成員也能夠初始化靜態成員,但靜態只讀字段除外
靜態構造函數只被執行一次,可是CLR也不能肯定它何時被執行,它的執行方式有兩種,precise和before-field-init,這個會在下一篇文章中詳細給你們介紹,這裏先提出給你們一個思考的空間。而實例構造函數在每次建立對象實例時都會被執行,建立幾個就會執行幾回
一個類只能有一個靜態構造函數,卻能夠有多個實例構造函數
靜態字段的初始值在靜態構造函數調用以前被指定,構造函數的執行順序大體以下圖所示:
下面就直接總結下它們之間的區別:
靜態成員包括靜態字段和靜態字段,靜態字段通常實現爲private,靜態屬性通常實現爲public,從而來體現類的封裝性
靜態成員和類相關聯,不依賴於對象而存在,只能由類來訪問;實例成員與具體類相關聯,只能由對象實例訪問
靜態成員無論建立多少實例對象,都在內存中只有一份,實例成員每建立一個實例對象,都會在內存中分配一塊內存區域。
相似於靜態字段和屬性,靜態方法共享代碼段,一樣以static關鍵字來標識靜態方法,對於他們之間的區別總結爲:
靜態方法只能訪問靜態成員和方法,可是能夠間接經過建立實例對象來訪問實例字段、屬性和方法;實例方法既能夠訪問實例成員也能夠訪問靜態成員
靜態方法由類方法‘實例方法由對象訪問
靜態方法不能引用this關鍵字,而實例方法能夠
靜態方法不能被標識爲virtual、abstract或override,靜態方法能夠被派生訪問,可是不能被派生類重寫
Main方法爲靜態的,因此Main方法不能直接訪問類中的實例字段、屬性和方法,不然編譯器會報錯
靜態方法通常用於做爲通用的工具類來實現
在性能上,靜態方法和實例方法的差異不大。由於,它們都是在JIT加載類的時候分配內存的,不一樣的是靜態方法是以類爲引用,而實例方法是以對象爲引用,建立實例時,不會再爲靜態方法分配內存,全部實例對象共用一個類的方法代碼,因此,靜態方法和實例方法的調用,區別僅在於靜態方法能夠直接調用,而實例方法須要當前對象指針指向該方法,在性能上差不併不大。
到這裏,本文章的內容就介紹完了,經過對靜態特徵和非靜態特徵的由來來揭開一些都是源於生活的觀點,而後再詳細分析了靜態特徵與非靜態特徵在C#語言中的區別,但願這些總結能夠幫助你們在複習基礎知識的時候能夠有用。同時也是本身的一個複習筆記的。