简体   繁体   中英

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.

I was looking at this article: Implementing a Dispose Method on MSDN and was confused by this particular line:

To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.

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"

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?

To investigate, I wrote a console application containing the following 3 lines:

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 . And following this train of thought I asked myself, "How can you call 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?

在此处输入图片说明

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?

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. 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)

There is nothing special about Dispose except for the fact that a using statement can call it for you. Other than that, it is just like any other .NET function. It does not magically set any variables to null , cause exceptions to be thrown if the object is used again, or anything like that.

Likewise, IDisposable is not a special interface in any way except that objects in a using statement must implement it. You could consider a using statement to be something like this:

// using(var a = somethingDisposable()) {otherCode();}
var a = somethingDisposable();
try
{
    otherCode();
}
finally
{
    if(a != null)
        ((IDisposable)a).Dispose();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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