Domanda

First in this MSDN page

there is a standard Dispose pattern. And there is a bool as the parameter of the protected Dispose method to tell the GC whether managed resources are freed manually already, so that the GC does not need to care about them.

Now the question is, what exactly should be done inside the if (disposing) {} block? Normally the GC cleans up managed resources, so one doesn't need to do anything special. But since inside this block, one needs to explicitly clean up managed resources, does that mean one just set all the fields and stuff in the object to null?

Second, isn't it just nicer to have just one destructor (or finalizer whatever it calls) in the language? And then in the GC design, just put a bit to determine if the destructor is already called so that there is no need to garbage collect it, or the destructor is not yet called and the GC should clean it up. I found the Dispose pattern quite complicated, and I am very confused what to clean up in which function and how to clean up in derived classed. And by using a signle destructor design, the GC just cleans things up when they are not cleaned up yet, and does not clean up when they are already.

Greetings

PS: So is this also a good and simpler pattern to clean up objects?

class Foo
{
    bool unmanagedDisposed = false;
    void Dispose() {/*clean up unmanaged resources*/ unmanagedDisposed = true;}
    ~Foo() {if (!unmanagedDisposed) Dispose();}
}

So if the programmer knows and remembers to call Dispose(), nothing to do in the finalizer, otherwise clean up unmanaged resources in the finalizer. And here we don't need to care about those managed resources.

È stato utile?

Soluzione

what exactly should be done inside the if (disposing) {} block?

You clean up the managed resources, ie you call Dispose() on all IDisposable objects that you own at that point.

to explicitly clean up managed resources, does that mean one just set all the fields and stuff in the object to null?

No, it does not mean that. It's only about IDisposable objects.

isn't it just nicer to have just one destructor (or finalizer whatever it calls) in the language?

We only have one destructor aka Finalizer and Dispose() is not it. That makes the rest of your paragraph irrelevant.

We have the Disposable pattern and the GC, they are related and cooperating but not the same. The GC manages memory and only memory. IDisposable is for managing resources (stream, connections, bitmaps).

Altri suggerimenti

Basically, you only need to implement the full ~Destructor() pattern with dispose if you have a class that has unmanaged fields or properties.

If all of your fields and properties are managed and not disposable, then you do not need to implement IDisposable at all.

If one of your fields or properties are disposable, then you need to just implement the IDisposable pattern. You don't necessarily have to go the whole hog with the above pattern.

If in the last case you do have an unmanaged resource in a field or property (e.g. a native pointer to something, a database connection other than ADO or other managed connections) then .net has no idea how to clean it up when the garbage collector rolls around.

In this case, you need to consider two places where your object will be cleaned up. Either it will be cleaned up by the developer calling Dispose() like he should, or he'll forget. If he forgets, and you have a destructor, then it's put on a finalization queue.

This is where the Dispose(disposing) call comes in. If the developer is good and calls Dispose(), then you send in true so that the managed resources can be cleaned up as well.

If the developer has not called dispose and the poor object ends up on the finalization queue, then calling Dispose() on the managed objects will throw an exception because they don't exist anymore. So in this case you send in a False, so that the managed resources are skipped and avoid the exception. I'm not sure about this, but legends say that throwing an exception on the finalization queue quits the whole process and could even end the world. So don't do it.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top