程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C#.Net中的非托管代碼清理(1)

C#.Net中的非托管代碼清理(1)

編輯:關於C語言

這兩天幫助其它項目組RevIEw代碼,發現有些地方實現了IDispose接口,同時也發現了一些關於IDispose的問題:

1.A類型實現了IDispose接口,B類型裡面含有A類型的字段,B類型沒有實現IDispose接口

2.一個類裡面實現了Finalize終結器,同時也實現了IDispose接口,但在Dispose方法裡面沒有調用GC.SuppressFinalize(this)方法.

下面我對以上兩個問題分別分析一下,並提出解決方案。

問題1

如果A類型裡面有非托管資源需要在實現的IDispose接口裡面釋放,由於B類型沒有實現IDispose接口,B類型的使用者要想釋放A類型的非托管資源並不方便.這樣的話,就有可能忘記了釋放A類型的非托管資源.

解決方案:

實現B類型的IDispose接口,在Dispose方法裡面調用A類型的Dispose方法.這樣,B類型的使用者在調用B類型Dispose的同時,就把A類型的Dispose也調用了.

問題2

在Dispose方法裡面沒有調用GC.SuppressFinalize(this)方法,會有什麼問題呢,這樣會導致垃圾回收器不能對 這個類型的對象及時回收. 當GC開始工作的時候,它首先將沒有終結器的垃圾對象從內存中移除,有終結器的所有對象則添加到一個垃圾隊列當中。GC會調用一個新線程來執行這些對象的 終結器。當終結器執行完畢後,這個對象會從隊列中被移除。這個對象在隊列中移除之後,當GC再次開始工作的時候,這個對象才能夠被回收,所以有終結器的對 象會比沒有的在內存中保留更長的時間。在後面我會對這裡再詳細的描述一下.

解決方案:

在Dispose方法中調用GC.SuppressFinalize(this)方法.這樣的話,就不會把有終結器的對象則添加到垃圾隊列當中.

切入正題

.Net中,非托管代碼清理有兩種方式:Finalize方式和Dispose方式.

Finalize方式:通過對自定義類型實現一個Finalize方法來釋放非通過資源.

從.Net2.0開始,C#編譯器不能對Finalize進行顯示的調用和重寫,必須使用析構函數來實現它.

class A
{
~A()
{
釋放資源;
}
}

上面的代碼就是通過Finalize方式來釋放資源的跟C++用析構函數釋放資源的代碼很象.

但是它實現方式和C++不同,因為它是由垃圾回收器來管理內存的.

大家看到了,用Finalize方式釋放非托管資源很簡單,但是如果你了解了他的實現方式,你可能就不會選擇用它來釋放非托管資源.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved