您好,登錄后才能下訂單哦!
在C#中,靜態和非靜態的特征對于我們來說是再熟悉不過了,但是很少看到有一篇文章去好好地總結靜態和非靜態它們之間的不同,為了幫助大家更好地去理解靜態和非靜態特征, 所以將在這篇文章中幫大家全面總結下它們之間的不同,包括靜態類,靜態成員和靜態構造函數。希望在大家鞏固基礎的時候可以拿出來好好復習下的。下面廢話不多了,直接進入我們今天的主題。
在自定義類或看.NET Framework類庫中都可以發現,類中大部分都是具體實例特征(也就是沒有static標識的),同時我們也能看到一些具有靜態特征的類或成員,例如我們經常使用的Console類以及WriteLine方法就是靜態的。然而有些朋友會疑惑,為什么還要有靜態特征的呢?干脆都定義為實例的好了? 然后靜態特征的存在肯定有它存在的原因的,并不是我們就是要這么定義的,其實我一直認為不管是什么都是源于生活的, 技術的實現也是一樣,比如我們開發程序,需要掌握技術外,其實更重要的是業務邏輯這塊的,如果你都不知道你開發的東西是怎樣的一個流程,即使你技術再牛做出來的東西都是反人類的東西(也就是指不符合用戶的用戶習慣和之前的一個業務需求),其實靜態特征的存在也是源于生活的,對于類好比就是我們現實生活中的人或事物,靜態特征和非靜態特征就好比生活中人或事物具有的特征, 我們詢問人的時候或者電視劇警察查案件的時候,都會聽到這樣一句話 "那個人有什么特征?"或 “嫌疑犯有什么特征?多高,年齡等” 其實高度、年齡、性別都是一個人的特征,所以這些在語言范疇就需要為其進行定義了,也就是我們定義的實例成員了,然而有些特征需要被所有對象實例所共有的,這些特征在語言范疇就定義為靜態特征,具體哪些特征可以定義為靜態特征呢? 其實這點一樣是源于生活的,所以我們在開發軟件的過程中,必不可少的一個流程就是需求分析了,只有在了解客戶需求的條件下才能進行之后的所有流程的, 例如一個班級有很多學生,每個學生是一個實體,在語言范疇就可以定義一個類,當我們需要一個學生的時候就可以通過new 關鍵字創建一個出來(說到這里又讓我想到了惡搞泰囧的圖片——你有對象嗎?沒對象,你們程序員可以自己new一個啊?),然而我們創建出來的學生他們都有一些共有的特征,如同一個班級,學校等, 如果我們把班級、學校這樣的特征也定義為實例的話,那么我們不是每次創建對象實例的時候都為這些共有的特征分配一次內存的,這樣不僅對內存空間的浪費也是不滿足生活常識的,此時我們就可以把班級、學校這樣的特征定義為靜態特征,這樣所有實例都可以共享這兩個特征,并且不需要為每個對象實例分配內存。
靜態類和非靜態類在C#中定義基本是一樣的,只是靜態類定義需要加上static修飾符而已。下面就直接總結下它們之間的區別:
靜態類只能包含靜態成員,否則會拋出編譯錯誤;然而非靜態類既可以包含非靜態成員也可以包含靜態成員
靜態類是不能實例化,之所以不能實例化,是因為靜態類會導致C#編譯器將該類同時標記為abstract和sealed,并且編譯器不會在類型中生成一個實例的構造函數,從而導致靜態類不能實例化,具體原因可以見下圖;非靜態類可以,并且靜態成員的訪問只能通過類來進行訪問,因為靜態成員是屬于類的。
publicstaticclass StaticClass { privatestaticstring name; }
上面代碼用IL反匯編程序得到的IL代碼結構為:
靜態構造函數用來初始化類中的靜態成員的,包括靜態字段和靜態屬性,并且靜態構造函數是不能帶有參數、不能有訪問修飾符,靜態構造函數的調用是由CLR第一次調用類成員之前執行的。
下面還是直接總結下靜態構造函數與實例構造函數之間的區別:
靜態構造函數可以與無參的實例構造函數同時存在
靜態構造函數在CLR加載類時執行,然而實例構造函數在每次實例創建時都會執行
靜態構造函數只能對靜態成員初始化,不能對非靜態成員進行初始化操作,然而實例構造函數,既可以初始化實例成員也可以初始化靜態成員,但靜態只讀字段除外
靜態構造函數只被執行一次,但是CLR也不能確定它什么時候被執行,它的執行方式有兩種,precise和before-field-init,這個會在下一篇文章中詳細給大家介紹,這里先提出給大家一個思考的空間。而實例構造函數在每次創建對象實例時都會被執行,創建幾個就會執行幾次
一個類只能有一個靜態構造函數,卻可以有多個實例構造函數
靜態字段的初始值在靜態構造函數調用之前被指定,構造函數的執行順序大致如下圖所示:
下面就直接總結下它們之間的區別:
靜態成員包括靜態字段和靜態字段,靜態字段一般實現為private,靜態屬性一般實現為public,從而來體現類的封裝性
靜態成員和類相關聯,不依賴于對象而存在,只能由類來訪問;實例成員與具體類相關聯,只能由對象實例訪問
靜態成員不管創建多少實例對象,都在內存中只有一份,實例成員每創建一個實例對象,都會在內存中分配一塊內存區域。
類似于靜態字段和屬性,靜態方法共享代碼段,同樣以static關鍵字來標識靜態方法,對于他們之間的區別總結為:
靜態方法只能訪問靜態成員和方法,但是可以間接通過創建實例對象來訪問實例字段、屬性和方法;實例方法既可以訪問實例成員也可以訪問靜態成員
靜態方法由類方法‘實例方法由對象訪問
靜態方法不能引用this關鍵字,而實例方法可以
靜態方法不能被標識為virtual、abstract或override,靜態方法可以被派生訪問,但是不能被派生類重寫
Main方法為靜態的,所以Main方法不能直接訪問類中的實例字段、屬性和方法,否則編譯器會報錯
靜態方法一般用于作為通用的工具類來實現
在性能上,靜態方法和實例方法的差別不大。因為,它們都是在JIT加載類的時候分配內存的,不同的是靜態方法是以類為引用,而實例方法是以對象為引用,創建實例時,不會再為靜態方法分配內存,所有實例對象共用一個類的方法代碼,所以,靜態方法和實例方法的調用,區別僅在于靜態方法可以直接調用,而實例方法需要當前對象指針指向該方法,在性能上差不并不大。
到這里,本文章的內容就介紹完了,通過對靜態特征和非靜態特征的由來來揭開一些都是源于生活的觀點,然后再詳細分析了靜態特征與非靜態特征在C#語言中的區別,希望這些總結可以幫助大家在復習基礎知識的時候可以有用。同時也是自己的一個復習筆記的。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。