20.如何手工釋放資源?
答:
.Net 平台在內存管理方面提供了GC(Garbage Collection),負責自動釋放托管資源和內存回收的工作。但在以下兩種情況需要我們手工進行資源釋放:一、由於它無法對非托管資源進行釋放,所以我們必須自己提供方法來釋放對象內分配的非托管資源,比如你在對象的實現代碼中使用了一個COM對象;二、你的類在運行是會產生大量實例(象 GIS 中的Geometry),必須自己手工釋放這些資源以提高程序的運行效率
最理想的辦法是通過實現一個接口顯式的提供給客戶調用端手工釋放對象,System 命名空間內有一個 IDisposable 接口,拿來做這事非常合適,省得我們自己再聲明一個接口了
示例:
using System;
using System.Collections.Generic;
using System.Text;
namespace Example20
{
class Program
{
class Class1 : IDisposable
{
//析構函數,編譯後變成 protected void Finalize(),GC會在回收對象前會調用調用該方法
~Class1()
{
Dispose(false);
}
//通過實現該接口,客戶可以顯式地釋放對象,而不需要等待GC來釋放資源,據說那樣會降低效率
void IDisposable.Dispose()
{
Dispose(true);
}
//將釋放非托管資源設計成一個虛函數,提供在繼承類中釋放基類的資源的能力
protected virtual void ReleaseUnmanageResources()
{
//Do something...
}
//私有函數用以釋放非托管資源
private void Dispose(bool disposing)
{
ReleaseUnmanageResources();
//為true時表示是客戶顯式調用了釋放函數,需通知GC不要再調用對象的Finalize方法
//為false時肯定是GC調用了對象的Finalize方法,所以沒有必要再告訴GC你不要調用我的Finalize方法啦
if (disposing)
{
GC.SuppressFinalize(this);
}
}
}
static void Main(string[] args)
{
//tmpObj1沒有手工釋放資源,就等著GC來慢慢的釋放它吧
Class1 tmpObj1 = new Class1();
//tmpObj2調用了Dispose方法,傳說比等著GC來釋放它效率要調一些
//個人認為是因為要逐個對象的查看其元數據,以確認是否實現了Dispose方法吧
//當然最重要的是我們可以自己確定釋放的時間以節省內存,優化程序運行效率
Class1 tmpObj2 = new Class1();
((IDisposable)tmpObj2).Dispose();
}
}
}