在這里,對象可以通過兩種方式被清除。第一種方式是通過 IDisposable 接口的 Dispose 方法。此方法在對象顯式地結束時被客戶代碼調用,它調用 InternalD" name="description" />
MILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在這里,對象可以通過兩種方式被清除。第一種方式是通過IDisposable接口的Dispose方法。此方法在對象顯式地結束時被客戶代碼調用,它調用InternalDispose(true)。在這種情況下所有的對象都被清除了。如果析構函數被調用,那么InternalDispose(false)被調用,此時只有外部資源會被釋放。如果我們已經執行了終止操作,那么我們自己的對象有可能已經被釋放了,此后對它們的引用有可能引起異常。
對GC.SuppressFinalize的調用會阻止垃圾收集器將對象放入終止隊列中。這樣做可以降低在一次GC過程中由于整理對象而引起的內存消耗,并且由于終止操作不會被調用,從而使性能得到提高。
對C#的優化
因此使用IDisposable.Dispose()來釋放資源是個很好的方式,它不但可以減少一些在托管堆上進行操作的內存需求,而且能夠減少必須執行終止操作的對象的數量。但是它使用起來比較麻煩,尤其是有多個臨時對象被創建的時候更是如此。為了能夠從IDisposable接口受益,C#客戶程序應該書寫象下面這樣的代碼:
OverdueBookLocator bookLocator = null;
try
{
bookLocator = new OverdueBookLocator();
// Use bookLocator here
Book book = bookLocator.Find("Eiffel, the Language");
.
.
.
}
finally
{
if(bookLocator != null)
{
IDisposable disp = bookLocator as IDisposable;
disp.Dispose();
}
}
finally中的代碼被用來在有異常發生時作適當的清理工作。為了C#客戶程序能夠簡單有效地使用Dispose模式,Beta2引入了using表達式。Using表達式允許你簡化你的代碼,因此上面的代碼可以寫成:
using(bookLocator = new OverdueBookLocator())
{
// Use bookLocator here
Book book = bookLocator.Find("Eiffel, the Language");
}
無論何時分配具有明確定義的生存期的類型時,你都應該使用using表達式。它能保證對IDisposable接口的適當調用,即使是在有異常發生的時候。
使用System.GC類
System.GC類用來訪問被.NET framework暴露出來的垃圾回收機制。這個類包含以下一些有用的方法:
● GC.SuppressFinalize 這個方法在前面已經描述過了,它能夠抑制終止操作。如果你已經將屬于一個對象的外部資源釋放了,調用這個方法來抑制此對象的終止操作的執行。
● GC.Collect 具有兩個版本。不帶參數的版本在托管堆的所有generation上執行回收動作。另一個版本帶有一個整型參數,此參數指明所要進行回收操作的generation。你將很少調用這個方法,因為垃圾收集器在需要的時候會自動調用它。
● GC.GetGeneration 返回作為參數傳入的對象所在的generation。這個方法在由于性能的原因而進行的調試和跟蹤中很有作用,但是在大部分應用中作用有限。
● GC.GetTotalMemory 返回堆中已經被分配的內存總量。由于托管堆的工作方式,這個數字并不精確,但是如果你以true作為參數的話,還是會得到一個比較接近的近似值。這個方法在計算之前會先執行一遍回收操作。
下面是使用這些方法的一個例子:
/// <summary>
/// Displays current GC information
/// </summary>
/// <param name="generation">The generation to collect</param>
/// <param name="waitForGC">Run GC before calculating usage?</param>
public void CollectAndAudit(int generation, bool waitForGC)
{
int myGeneration = GC.GetGeneration(this);
long totalMemory = GC.GetTotalMemory(waitForGC);
Console.WriteLine("I am in generation {0}.", myGeneration);
Console.WriteLine("Memory before collection {0}.", totalMemory);
GC.Collect(generation);
Console.WriteLine("Memory after collection {0}.", totalMemory);
}
關于本文作者
原文轉自:http://www.anti-gravitydesign.com