標籤:
記憶體回收時現代語言的標誌之一。記憶體回收解放了手工管理對象釋放的工作,提高了程式的健壯性,但是副作用就是程式碼可以對於建立對象變得隨意。
1、避免不必要的對象建立
由於記憶體回收的代價較高,所以C#程式開發要遵循的一個基本原則就是避免不必要的對象建立。以下列舉一些常見的情型。
a)、避免迴圈建立對象
如果對象並不會隨每次迴圈改變而改變狀態,那麼在迴圈中反覆建立對象將帶來效能損耗。例如下面的例子:
SqlBuildResults BuildUpdate(IEntityMap Map,IObjectValue date) { SqlBuildResults results = new SqlBuildResults(); foreach(IORMap ormap in map.Maps) { UpdateBuilder builder = new UpdateBuilder(); SqlBuildResults result = builder.BuildUpdate(ormap,date); if(result != null) results.AddRange(result); } return results; }
高效的做法是將builder對象提到迴圈外面建立。
b)、在需要的邏輯分支中建立對象
如果對象只在默寫邏輯分支中才被用到,那麼應該只在該邏輯分支中建立對象。例如:
protected virtual object OnGetRelation(string childAttrName, IAssociaton association, object relation) { ObjectRelationEventArgs args1 = new ObjectRelationEventArgs(association, relation, relation); if (this.GetRelation != null) { this.GetRelation(childAttrName, this.Anchor, args1); relation = args1.NewRelation; } return relation; }
正確的做法是:
protected virtual object OnGetRelation(string childAttrName, IAssociaton association, object relation) { if (this.GetRelation != null) { ObjectRelationEventArgs args1 = new ObjectRelationEventArgs(association, relation, relation); this.GetRelation(childAttrName, this.Anchor, args1); relation = args1.NewRelation; } return relation; }c)、使用常量避免建立對象
如下例,程式中存在大量new decimal(0)的代碼,這會導致小對象頻繁建立及回收;
if (convert1.FromDualQty.RateToBase == new decimal(0)) { comvert1.FromDualQty.RateToBase == UOMConvertRatio.GetRationBy(……); } if (convert1.ToQty.RateToBase == new decimal(0)) { comvert1.FromDualQty.RateToBase == UOMConvertRatio.GetRationBy(……); }
正確的做法是使用Decimal.Zero常量。另外,我們也可以學習這個設計手法,應用到類似情境中。
d)、使用StringBuilder做字串串連。
2、不要使用空解構函式
如果類中包含解構函式,則建立對象時會在Finalize隊列中添加對象的引用,以保證當對象無法到達時,人人可以調用到Finalize方法。記憶體回收 器在運行期間,會啟動一個低優先順序的線程處理該隊列。相比之下,沒有解構函式的對象就沒有沒有這些小號。如果解構函式為空白,這個消耗就毫無意義,只會導致 效能降低!因此,我們盡量不要使用空的解構函式。
從實際情況來看,許多是曾經在解構函式中包含有處理代碼,但後來因為種種原因被注釋掉或者刪除掉了,只留下一個空的解構函式。此時應該注意把解構函式本身注釋掉或者刪除掉。
3、實現IDisposable介面
記憶體回收事實上只支援託管記憶體的回收,對於其它的非託管的資源,例如:WindowsGDI控制代碼或資料庫連接,在解構函式中是否資源有很大問題,原因是記憶體回收依賴於記憶體緊張情況,雖然資料庫連接可能已瀕臨耗盡,但如果記憶體還很充足的話,記憶體回收是不會啟動並執行。
C#的IDisposable介面是一種顯式釋放資源的機制。通過提供using語句,還簡化了使用方式(編譯器自動產生try…finally塊,並在 finally塊中調用Dispose方法)。對於申請了非託管資源的對象,應為其實現IDisposable介面,並保證資源一旦超出using語句範 圍,即得到及時的釋放。這對於建構函式健壯且效能優良的程式非常有意義!
為防止對象的Dispose方法不被調用的情況發生,一般還要提供解構函式,兩者調用一個出來資源釋放的公用方法。同時,Dispose方法應調用 System.GC.SuppressFinalize(this),告訴記憶體回收行程無需在處理Finalize方法了。
原文地址:http://www.cnblogs.com/lijun198504/archive/2010/01/19/1651729.html
C#之記憶體回收