Effective C#(二)
生活随笔
收集整理的這篇文章主要介紹了
Effective C#(二)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
我勒個去……過了整整仨月,才看完一章,我是有多懶了。。。。不過最近工作忙,而且新房還裝修。一體檢還查出個過度疲勞。似乎賣苦肉計也沒啥意思哈。。。。以后盡量勤奮點吧!嗯啊~ Chapter 2 .NET Resource Management ? ? ?GC通過定義“代”的概念來優(yōu)化回收工作。可以篩選出更加有“潛質(zhì)”的回收對象。所有自上次GC以后創(chuàng)建的對象是第0代。經(jīng)過一次GC后仍存在的,升級為第1代。再經(jīng)過一次GC后仍存在的升級為第2代(最高)。每一次GC都會檢查第0代的對象,大約10次GC才會檢測一次第1代的,而大約100次GC才會檢測一次第2代的對象。這樣設(shè)計,是為了將局部變量快速地遍歷回收,同時保證一些全局的一直被使用的對象不每次都被遍歷。 ? ? ?在C#中,使用Finalizer來釋放資源并不是一個好主意。因為Finalizer只有在對象被GC時才被調(diào)用。所以被調(diào)用的時機是未知的。 ? ? ?存在Finalizer的對象,必須要等到下一個GC周期才能被析構(gòu)。因為Finalizer不能在GC的線程中被調(diào)用。GC會將存在Finalizer的對象存入一個隊列,再開一個線程給他們。所以Finalizer會使本可以被迅速回收的局部變量的代數(shù)迅速升級。
- Prefer Member Initializer To ?Assignment Statements
-
- 隨著類的構(gòu)造函數(shù)的增多,可能會造成一些成員變量沒有被同步地初始化的情況。避免這種情況的一個解決辦法就是在聲明它們時就初始化。編譯器會將聲明時初始化編譯為所有構(gòu)造函數(shù)方法體之前的一段初始化代碼,而且是按照你定義的順序。這樣保證構(gòu)造函數(shù)中所有聲明初始化已經(jīng)完成。
- 但是,當你需要給變量初始化為0或者null時,不要使用聲明初始化。如果不使用,系統(tǒng)會在較低的level為這片內(nèi)存區(qū)域設(shè)置為0或者null。這是非常高效的。反之,編譯器需要在代碼中加入額外的賦值指令。這樣做不錯,只是效率不如前者高。
- 當你需要在構(gòu)造函數(shù)中根據(jù)參數(shù)初始化一些成員變量時,不要使用聲明初始化。因為這樣聲明初始化的對象生成后直接就被GC掉。
- 當你需要捕捉初始化的異常時,不要使用聲明初始化。因為它無法放在try...catch中。
- Use Proper Initialization For Static Class Member
-
- 靜態(tài)構(gòu)造函數(shù)在對應(yīng)的類型第一次訪問之前被調(diào)用。所以可以用來進行需要一些邏輯的靜態(tài)初始化。例如:異常捕獲。
- Utilize using and try/finalize for Resource Cleanup
-
- 所有含有非托管資源的類型都實現(xiàn)的IDisposable接口。應(yīng)當顯示調(diào)用他們的Dispose()方法來釋放內(nèi)存。
- 當對象拋出異常時,Dispose()可能沒有被調(diào)用。最簡單的解決方法是使用using將非托管對象包圍起來。using會在編譯時生成try/finalize語句塊。
- using(){}中的對象類型必須是實現(xiàn)了IDisposable接口的。如果不是,可以用as騙過編譯器。但效果相當于using(null){},不會有任何意義。
- 當有多個非托管對象同時出現(xiàn)時,可以自己手寫try/finalize語句塊。嵌套using()也成,只是結(jié)構(gòu)會比較難看。。。
- 也可以用Close()來釋放非托管資源。但與Dispose()不同的時,Close()在釋放資源后不會將它從GC的Finalize Queue中移除。所以Dispose()比Close()更好。
- Dispose()不會將對象從內(nèi)存移除,只是讓對象釋放非托管資源,例如數(shù)據(jù)庫連接。這時,這塊內(nèi)存還在,但是數(shù)據(jù)庫連接已經(jīng)斷開了。
- Avoid Creating Unnecessary Objects
-
- 作者最想說的就是不要在方法里面創(chuàng)建引用類型的對象,尤其是頻繁調(diào)用的方法。如何避免呢,有下面三個方法。
- 把一直重復(fù)使用的對象提升為全局對象,避免每次都創(chuàng)建。
- 一些常量的對象寫成靜態(tài)屬性。只在獲取時創(chuàng)建。
- 對于一些不可變的對象,實現(xiàn)一個可以構(gòu)造器。例如string和StringBuilder。
- Implement the Standard Dispose Pattern
-
- 實現(xiàn)你自己的Dispose模式時,一定要寫Finalizer,雖然會有一些性能損耗,但可以保證非托管資源一定能被釋放。
- 實現(xiàn)Dispose模式需要做4件事:
-
- 釋放非托管資源
- 釋放托管資源
- 設(shè)置一個標志位,標明這個對象已經(jīng)被Dispose。其它方法被調(diào)用時,拋出ObjectDisposedException。
- 觸發(fā)Finalization。
- 只在需要的時候?qū)慒inalization,否則會造成性能開銷。
- 永遠不要在Finalizer和Dispose中做釋放資源以外的事情。
- 可以寫一個Helper method:void Dispose(bool isDisposing)。
- Distinguish between Value Types and Reference Types
-
- 值類型一般用于存儲數(shù)據(jù),而引用類型一般用于包含行為、實現(xiàn)繼承和多態(tài)。
- 決定一個自定義的類型是值類型還是引用類型很重要。將一個引用類型改為值類型會帶來深遠的影響。值類型將不再支持繼承和多態(tài),而且作為參數(shù)或返回值傳遞時,會產(chǎn)生一個新的對象。
- 如果拿不定主意,選擇引用類型。
- Ensure 0 is a Valid State for Value Types
-
- 所有的值類型都會在初始化時將內(nèi)部的值置為0,這是C#語言的特性,你無法改變,你只能去適應(yīng)。
- 對于enum,最好將0作為一個合理的值。否則EnumType aaa = new EnumType();這樣的語句會造成一個無效的enum值。如果是作為位操作使用,請將0作為None使用,即每一種情況都沒有選中。
- Prefer Immutable Atomic Value Types
-
- 不可變的數(shù)據(jù)類型更易于維護。然而創(chuàng)建不可變數(shù)據(jù)并不容易。防止struct中的字段被濫改,可以使用屬性加以控制。但是過多的屬性也帶來過多的隱患。可以將屬性的set設(shè)為private。只在構(gòu)造函數(shù)中進行賦值。如果更嚴格一點,可以將字段設(shè)為readonly,并且去掉屬性的set。
- 對于struct中的引用類型要加倍小心。它們可能從外部被改變。保險的解決方案是在構(gòu)造函數(shù)中進行復(fù)制,或者在屬性的get時進行復(fù)制。
- 其它的防止struct中的字段被改變的方式兩個。一個是使用工廠方法。還有就是將多部操作進行封裝來構(gòu)造不可變數(shù)據(jù),例如StringBuilder和string。
轉(zhuǎn)載于:https://www.cnblogs.com/sigmadruid/p/5054330.html
總結(jié)
以上是生活随笔為你收集整理的Effective C#(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: css cursor 的可选值(鼠标的各
- 下一篇: Atitit.获取approot api