Clarify some things about IDisposable interface. Is instance (must be) equals null after calling Dispose?

笑着哭i 提交于 2021-02-20 02:50:14

问题


I have a class which implements IDisposable interface.

using System;

class A : IDisposable
{
        public void Dispose()
        {
            Stop(); // some actions to stop internal threads

            this = null;
        }
}

Why can't I assign this = null in Dispose method ? I know 'this' is read-only.

For example:

A a = new A();
a.Run();
// ...
a.Dispose();
// i want in this line a = null

I thought IDisposable and Dispose method guarantee that instance of class A will be equals to null after calling Dispose(). But it's not true.


回答1:


Just to add to what's already been said:

It's important to realize that there are objects, and there are references (variables), and these are not the same thing.

When you write var a = new object(); you're doing two things:

  1. Creating a new object instance. This instance has no "name" -- just a location in memory. It is what it is. But, just so we have something to call it, let's call it "Bob."
  2. Declaring a variable a, which references the object just created.

Now, when you write a = null;, you're doing nothing to Bob. You're changing a to reference, instead of Bob, null, or in other words, "no object." So you can no longer access "Bob" using a.

Does this mean now Bob doesn't exist? No. Bob's still right where he was.

Consider this (which is basically the scenario Henk mentioned):

var a = new object(); // Again, we're calling this object Bob.
object b = a;

Now, b is another variable, just like a. And just like a, b references Bob. But again, just as with a, writing b = null; does nothing to Bob. It just changes b so that it no longer points to an object.

Here's where I'm going with this. You seem to have been under the impression that doing this:

a.Dispose();

...somehow also did this:

a = null;

...which was somehow equivalent to doing this:

Bob= null; // nowBobis no object?

But if that were the case, then b (above) would now point to no object, even though it was never set to null!

Anyway, from my explanation above, hopefully it is clear that this is simply not how the CLR works. As Jon has pointed out, the IDisposable interface is actually not related to memory being freed. It is about releasing shared resources. It does not -- cannot -- delete objects from memory, as if it did then we would have the behavior I've described above (references suddenly becoming invalid out of nowhere).

I know this was only loosely related to your specific question about IDisposable, but I sensed that this question was coming from a misconception about the relationship between variables and objects; and so I wanted to make that relationship clearer.




回答2:


No, Dispose is just a method like any other method as far as the CLR is concerned. C# has support for it via using statements (and foreach with the iterator being disposed), but other than that it has no significance. In particular, it doesn't directly interact with the garbage collector, or affect any variables referring to the disposed object. (Some implementations of IDisposable may also have finalizers which call Dispose, but they're logically distinct concepts.)

Note that an object isn't necessarily unusable after being disposed. For example, disposing of a MemoryStream doesn't clear out the data in memory - using ToArray on it afterwards will still work.

Indeed, the documentation for IDisposable explicitly talks about the possibility of it being used to reset an object for reuse:

Use this method to close or release unmanaged resources such as files, streams, and handles held by an instance of the class that implements this interface. By convention, this method is used for all tasks associated with freeing resources held by an object, or preparing an object for reuse.




回答3:


It is not possible but also not useful.

Consider b in:

A b = a; // alias
a.Dispose();
// i want in this line a = null

And it's not really a problem, there still is an object that a and b reference to. It just has its internal state changed to 'closed'. Some IDisposable classes have a bool IsDisposed member that you can safely call after Dispose()




回答4:


Your assumption is incorrect. Dispose() doesn't reclaim the instance and doesn't affect the reference.

It is a utility method that gets some special attention from the framework/compiler that allows you to easily clean up resources not handled by the GC. Other than that it is just a regular method. Calling a method should not affect the reference itself.

The recommendation for implementing Dispose() specifically states

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



来源:https://stackoverflow.com/questions/3649573/clarify-some-things-about-idisposable-interface-is-instance-must-be-equals-nu

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!