Sample use of a C# Destructor

2019-05-05 09:46发布

问题:

I'm reading about destructors in C# but I'm having trouble finding a decent use-case for it.

Could someone provide an example of usage with an explanation?

Much, much appreciated.

Update
The code sample in the book implements both a Desctuctor and a Dispose() method, see this code snippet from the book.

class MyClass
{
    bool disposed = false; // Disposal status
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    ~MyClass()
    {
        Dispose(false);
    }
    protected virtual void Dispose(bool disposing)
    {
        if (disposed == false)
        {
            if (disposing == true)
            {
                // Dispose the managed resources. Factored Dispose

            }
            // Dispose the unmanaged resources.

        }
        disposed = true;
    }
}

Marko

回答1:

Finalizers are very rarely needed now. They used to be required when you had direct access to native resources - but now you should usually be using SafeHandle instead.

Joe Duffy has an excellent post about this which goes into rather more details than I would be able to write myself - so go read it :)

A quick note on terminology: the ECMA version of the C# spec refers to them as finalizers; the Microsoft version of the spec has always referred to them as destructors and continues to do so.



回答2:

They're finalizers, not destructors. They're often used to clean up unmanaged resources - if you wrote your own file class, then you would need to use the finalizer to clean up the native file handle.



回答3:

Finalizers are rarely needed in C# and adding one can cause the garbage collector to take longer to clean up the garbage as an extra pass is required to run the finalizer. Instead you should normally use the IDisposable pattern.

An example usage of a finalizer is if you suspect resource leakage you can use it when debugging to check if Dispose has been called correctly before the object is garbage collected. If an object that holds unmanaged resources has its finalizer called before Dispose has been called it could be a sign of a resource leakage. But since the finalizer may not ever be called it should not contain any application critical logic.



回答4:

What do you mean by destructor? C# has

  • The IDisposable pattern which you'd use for deterministic destruction
    Useful to close Handles when you don't need them anymore. So they are closed now and not whenever the GC decides to collect the object which might be much later or not at all.
    Or in pure managed code to tell an object to remove itself from the object graph, unsubscribe from events,...
    Commonly used with a using statement
  • The Finalizer which is almost useless. It runs at an unknown time, it might not run at all,...
    The only thing I use it for is to remind me that I forgot to call Dispose on something
    While it has the syntax of a C++ destructor I don't consider it the equivalent of a C++ destructor. I prefer to think about Dispose() as the destructor.
  • Critical finalization and SafeHandles which you use for native resources

I think instead of the pattern you posted modern code should own a private SafeHandle and call it's Dispose method in it's own Dispose.



回答5:

C# doesn't have 'destructors' as you're probably thinking about them. With .NET's garbage collector, object collection won't happen right away when your class goes out of scope.

I think what you're more interested in is the IDisposable pattern. That is a deterministic way for you to clean up resources your object uses.

In addition, .NET classes can have 'finalizers' which are executed when an object is collected. It can be used to call dispose if the original caller of your object neglected to.

But, implementing a finalizer in your class queues it up for special processing for GC and might have a performance impact.



回答6:

The IDisposable interface provides a method to use as a destructor/finalzer.

What I mean is that you may implement the IDisposable interface in order to free the resources your object is using. As the others have said, this is not the same thing as a good old destructor, since the Dispose() method will not be called directly by yourself, but by the managed code to dispose of your object after a while.