[英]What exactly does calling Dispose do?
我一直在嘗試加深對垃圾收集,托管和非托管資源以及有關內存管理的“適當的設計原則”的理解,因為我有興趣進入“較低級別”的編程以及這類性質的東西。
我了解您應該使用using
塊或其他解決方案來確保這些不受管理的資源確實得到處置,但是我不了解幕后情況。
我在看這篇文章:在MSDN上實現Dispose方法 ,並被這行特別困惑:
為了確保始終正確地清理資源,Dispose方法應可多次調用而不會引發異常。
讓我們看一下它們為處理模式提供的示例代碼:
class DerivedClass : BaseClass
{
// Flag: Has Dispose already been called?
bool disposed = false;
// Instantiate a SafeHandle instance.
SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
// Protected implementation of Dispose pattern.
protected override void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
handle.Dispose();
// Free any other managed objects here.
}
// Free any unmanaged objects here.
disposed = true;
// Call base class implementation.
base.Dispose(disposing);
}
}
我相信上面引用的文字基本上是這樣說的:“我們添加了一個bool disposed
屬性,以便我們可以檢查是否為true
然后return
true
。如果為false
那么我們將處理實際資源。這樣我們就不會實際多次處置”
但這對我來說沒有意義。 如果我們已經擺脫了一個對象,您如何第二次調用Dispose
?
為了進行調查,我編寫了一個包含以下3行的控制台應用程序:
var cmd = new SqlCommand();
cmd.Dispose();
cmd.Dispose();
這可以毫無問題地進行編譯和執行-考慮到文章中引用的文字,這很有意義。 但我不了解實際情況。
我設置一個斷點,然后跨過每一行。 在調用第一個Dispose
之后,我希望Visual Studio中的Locals窗口告訴我cmd
為null
。 然后按照這種思路,我問自己:“你怎么稱呼Dispose
on null
?” 顯然,你不能。 那到底是怎么回事? 為什么在第一次處置后, cmd
仍然是SqlCommand
對象?
Dispose
到底能做什么,並且如果我已經處置了對象,為什么它在所有意圖和目的上似乎仍然存在?
為什么/以下內容如何編譯和運行而不會出現問題?
var cmd = new SqlCommand();
cmd.Dispose();
cmd.CommandText = "I figured this would throw an exception but it doesn't";
IDisposable
接口由多個使用類調用,並且-如Dark Falcon所述-當您將類的用法封裝在using塊中時。 這樣可以更輕松地保持非托管資源的清潔。 但是Dispose
就像其他任何方法一樣,不要與析構函數/ finalizer混淆(這顯然是您期望的)
Dispose
沒什么特別的,除了using
語句可以為您調用它。 除此之外,它與任何其他.NET函數一樣。 它不會神奇地將任何變量設置為null
,如果再次使用該對象或諸如此類,則會引發異常。
同樣, IDisposable
在任何方面都不是特殊的接口,只是using
語句中的對象必須實現它。 您可以考慮using語句是這樣的:
// using(var a = somethingDisposable()) {otherCode();}
var a = somethingDisposable();
try
{
otherCode();
}
finally
{
if(a != null)
((IDisposable)a).Dispose();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.