[英]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.