简体   繁体   English

调用Dispose到底能做什么?

[英]What exactly does calling Dispose do?

I've been trying to increase my understanding of garbage collection, managed & unmanaged resources, and "proper design principles" regarding memory management as I am interested in getting into "lower level" programming and things of that nature. 我一直在尝试加深对垃圾收集,托管和非托管资源以及有关内存管理的“适当的设计原则”的理解,因为我有兴趣进入“较低级别”的编程以及这类性质的东西。

I understand that you're supposed to use using block or some other solution for ensuring these unmanaged resources do in fact get disposed, but I don't understand what is happening under the hood. 我了解您应该使用using块或其他解决方案来确保这些不受管理的资源确实得到处置,但是我不了解幕后情况。

I was looking at this article: Implementing a Dispose Method on MSDN and was confused by this particular line: 我在看这篇文章:在MSDN上实现Dispose方法 ,并被这行特别困惑:

To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception. 为了确保始终正确地清理资源,Dispose方法应可多次调用而不会引发异常。

Lets look at the example code they provide for the dispose pattern: 让我们看一下它们为处理模式提供的示例代码:

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);
   }
}

I believe what the quoted text above is basically saying is, "We added a bool disposed property so that we can check if that's true and return if so. If it's false then we dispose of the actual resources. That way we don't actually dispose of something multiple times" 相信上面引用的文字基本上是这样说的:“我们添加了一个bool disposed属性,以便我们可以检查是否为true然后return true 。如果为false那么我们将处理实际资源。这样我们就不会实际多次处置”

But this didn't make sense to me. 但这对我来说没有意义。 If we've gotten rid of an object, how can you call Dispose on it a second time? 如果我们已经摆脱了一个对象,您如何第二次调用Dispose

To investigate, I wrote a console application containing the following 3 lines: 为了进行调查,我编写了一个包含以下3行的控制台应用程序:

var cmd = new SqlCommand();
cmd.Dispose();
cmd.Dispose();

This compiles and executes without problem -- which makes sense, given the quoted text from the article. 这可以毫无问题地进行编译和执行-考虑到文章中引用的文字,这很有意义。 But I don't understand what's actually happening. 但我不了解实际情况。

I set a breakpoint and stepped over each line. 我设置一个断点,然后跨过每一行。 After the first Dispose is called, I expected the Locals window in Visual Studio to tell me that cmd is null . 在调用第一个Dispose之后,我希望Visual Studio中的Locals窗口告诉我cmdnull And following this train of thought I asked myself, "How can you call Dispose on null ?" 然后按照这种思路,我问自己:“你怎么称呼Dispose on null ?” Obviously, you can't. 显然,你不能。 So what is happening? 那到底是怎么回事? Why is cmd still a SqlCommand object after its been disposed of the first time? 为什么在第一次处置后, cmd仍然是SqlCommand对象?

在此处输入图片说明

What exactly does Dispose do, and if I've disposed of my object why does it seem to still exist for all intents and purposes? Dispose 到底能做什么,并且如果我已经处置了对象,为什么它在所有意图和目的上似乎仍然存在?

Why / How does the following compile and run without problem? 为什么/以下内容如何编译和运行而不会出现问题?

var cmd = new SqlCommand();
cmd.Dispose();
cmd.CommandText = "I figured this would throw an exception but it doesn't";

The IDisposable interface is being called by several consuming classes and - as already stated by Dark Falcon - when you encapsulate the usage of your class in a using block. IDisposable接口由多个使用类调用,并且-如Dark Falcon所述-当您将类的用法封装在using块中时。 This makes it easier to keep your unmanaged resources clean. 这样可以更轻松地保持非托管资源的清洁。 But Dispose is just like any other method and not to be confused with destructors/finalizers (which is what you apparently expected it to be) 但是Dispose就像其他任何方法一样,不要与析构函数/ finalizer混淆(这显然是您期望的)

There is nothing special about Dispose except for the fact that a using statement can call it for you. Dispose没什么特别的,除了using语句可以为您调用它。 Other than that, it is just like any other .NET function. 除此之外,它与任何其他.NET函数一样。 It does not magically set any variables to null , cause exceptions to be thrown if the object is used again, or anything like that. 它不会神奇地将任何变量设置为null ,如果再次使用该对象或诸如此类,则会引发异常。

Likewise, IDisposable is not a special interface in any way except that objects in a using statement must implement it. 同样, IDisposable在任何方面都不是特殊的接口,只是using语句中的对象必须实现它。 You could consider a using statement to be something like this: 您可以考虑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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM