C#之記憶體回收

來源:互聯網
上載者:User

標籤:

記憶體回收時現代語言的標誌之一。記憶體回收解放了手工管理對象釋放的工作,提高了程式的健壯性,但是副作用就是程式碼可以對於建立對象變得隨意。

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#之記憶體回收

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.