203

For example:

public class Person
{
    public Person()
    {
    }

    ~Person()
    {
    }
}

When should I manually create a destructor? When have you needed to create a destructor?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 8
    When you are feeling reckless. – capdragon Feb 04 '11 at 14:02
  • 1
    see also http://stackoverflow.com/questions/1076965/in-c-what-is-the-difference-between-a-destructor-and-a-finalize-method-in-a-clas – Ian Ringrose Feb 04 '11 at 15:23
  • I ended up using a destructor as a debugging aid based on the suggestion of Greg Beech: http://stackoverflow.com/questions/3832911/saving-a-class-to-disk-on-dispose-does-my-code-have-bugs/3833216#3833216 – Brian Feb 04 '11 at 19:58
  • 2
    The C# language calls these "destructors", but most people call them "finalizers" since that is their .NET name and it reduces confusion with C++ destructors (which are quite different). [How to Implement IDisposable and Finalizers: 3 Easy Rules](http://blog.stephencleary.com/2009/08/how-to-implement-idisposable-and.html) – Stephen Cleary Feb 04 '11 at 13:59

8 Answers8

258

UPDATE: This question was the subject of my blog in May of 2015. Thanks for the great question! See the blog for a long list of falsehoods that people commonly believe about finalization.

When should I manually create a destructor?

Almost never.

Typically one only creates a destructor when your class is holding on to some expensive unmanaged resource that must be cleaned up when the object goes away. It is better to use the disposable pattern to ensure that the resource is cleaned up. A destructor is then essentially an assurance that if the consumer of your object forgets to dispose it, the resource still gets cleaned up eventually. (Maybe.)

If you make a destructor be extremely careful and understand how the garbage collector works. Destructors are really weird:

  • They don't run on your thread; they run on their own thread. Don't cause deadlocks!
  • An unhandled exception thrown from a destructor is bad news. It's on its own thread; who is going to catch it?
  • A destructor may be called on an object after the constructor starts but before the constructor finishes. A properly written destructor will not rely on invariants established in the constructor.
  • A destructor can "resurrect" an object, making a dead object alive again. That's really weird. Don't do it.
  • A destructor might never run; you can't rely on the object ever being scheduled for finalization. It probably will be, but that's not a guarantee.

Almost nothing that is normally true is true in a destructor. Be really, really careful. Writing a correct destructor is very difficult.

When have you needed to create a destructor?

When testing the part of the compiler that handles destructors. I've never needed to do so in production code. I seldom write objects that manipulate unmanaged resources.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • "A destructor may be called on an object after the constructor starts but before the constructor finishes." But I can rely on field initializers to have run, right? – configurator Mar 31 '11 at 04:22
  • 14
    @configurator: Nope. Suppose the third field initializer of an object with a finalizer called a static method which caused an exception to be thrown. When would the fourth field initializer run? Never. But the object is still allocated and must be finalized. Heck, you don't even have a guarantee that fields of type double were *fully* initialized when the dtor runs. There could have been a thread abort halfway through writing the double and now the finalizer has to deal with a half-initialized half-zero double. – Eric Lippert Mar 31 '11 at 14:11
  • 1
    Excellent post, but should have said "should be created when your class is holding onto some expensive unmanaged object or causes large numbers of unmanaged objects to exist" - For a concrete example, I have a matrix class in C# that utilizes an underlying native C++ matrix class to do a lot of heavy lifting - I make a lot of matrices - a "destructor" is far superior to IDisposable in this specific case, because it keeps the managed and unmanaged sides of the house in better sync – Mark Mullin Feb 12 '12 at 18:06
  • 1
    pythonnet uses destructor to release GIL in unmanaged CPython – denfromufa Aug 26 '15 at 19:52
  • Respect the dead, even in programming. – call-me May 20 '16 at 16:31
  • 3
    Awesome article Eric. Props for this --> "Extra bonus fun: the runtime uses less aggressive code generation and less aggressive garbage collection when running the program in the debugger, because it is a bad debugging experience to have objects that you are debugging suddenly disappear even though the variable referring to the object is in scope. That means that if you have a bug where an object is being finalized too early, you probably cannot reproduce that bug in the debugger!" – Ken Palmer Aug 11 '16 at 18:10
  • 1
    @KenPalmer Yes the behaviour described in that paragraph hit me hard. Have been looking for the source of an AccessViolationException for ages now. Of course it occured only in the Release build. And of course it occoured some place else (Namely in the Read method of an UnmanagedMemoryStream) And of course I had forgotten the Article about how dangerous Finalizers are. Finally someone in the office suggested to put some kind of output into the Finalizer of every unmanaged object to track their existence. Needless to say, some of them got destroyed "early". – MrPaulch Oct 07 '16 at 15:28
  • @EricLippert I've referenced you in a new post asking a question about C# finalizers. – octopusgrabbus Jul 27 '17 at 17:08
17

It's called a "finalizer", and you should usually only create one for a class whose state (i.e.: fields) include unmanaged resources (i.e.: pointers to handles retrieved via p/invoke calls). However, in .NET 2.0 and later, there's actually a better way to deal with clean-up of unmanaged resources: SafeHandle. Given this, you should pretty much never need to write a finalizer again.

Nicole Calinoiu
  • 20,843
  • 2
  • 44
  • 49
  • 27
    @ThomasEding - [Yes it is](http://msdn.microsoft.com/en-us/library/0s71x931(v=vs.80).aspx). C# uses destructor syntax, but it's actually creating a [finalizer](http://en.wikipedia.org/wiki/Finalizer). [Again](http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx). – JDB Nov 13 '12 at 22:04
  • @JDB: The *linguistic construct* is called a destructor. I dislike the name, but that's what it's called. The act of declaring a destructor causes the compiler to generate a finalizer method which contains a little bit of wrapper code along with whatever appears in the body of the destructor. – supercat Apr 16 '19 at 18:28
8

You don't need one unless your class maintains unmanaged resources like Windows file handles.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • 5
    Well, actually, it's called a destructor – David Heffernan Feb 04 '11 at 14:01
  • 2
    Now I'm confused. Is it finalizer or destructor? –  Feb 04 '11 at 14:01
  • 4
    The C# spec does in fact call it a destructor. Some see this as a mistake. http://stackoverflow.com/questions/1872700/the-difference-between-a-destructor-and-a-finalizer – Ani Feb 04 '11 at 14:03
  • 1
    It's actually called a Destructor and it implicitly calls the Finalize method: http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx – HasaniH Feb 04 '11 at 14:05
  • 2
    @ThomasEding - [Yes it is](http://msdn.microsoft.com/en-us/library/0s71x931(v=vs.80).aspx). C# uses destructor syntax, but it's actually creating a [finalizer](http://en.wikipedia.org/wiki/Finalizer). – JDB Nov 13 '12 at 22:07
  • 2
    I love the comments here, real panto :) – Benjol Dec 03 '15 at 07:07
4

I have used a destructor (for debug purposes only) to see if an object was being purged from memory in the scope of a WPF application. I was unsure if garbage collection was truly purging the object from memory, and this was a good way to verify.

Neil.Allen
  • 1,606
  • 1
  • 15
  • 20
  • I do the same in WPF apps and not only. If a destructor is never called on a class that you know it is not used anymore, then you have to investigate more why this object is not garbage collected. If the breakpoint hits the destructor, then everything should be fine, otherwise you have a memory leak. – Alexandru Dicu Oct 15 '20 at 11:53
4

It's called a destructor/finalizer, and is usually created when implementing the Disposed pattern.

It's a fallback solution when the user of your class forgets to call Dispose, to make sure that (eventually) your resources gets released, but you do not have any guarantee as to when the destructor is called.

In this Stack Overflow question, the accepted answer correctly shows how to implement the dispose pattern. This is only needed if your class contain any unhandeled resources that the garbage collector does not manage to clean up itself.

A good practice is to not implement a finalizer without also giving the user of the class the possibility to manually Disposing the object to free the resources right away.

Community
  • 1
  • 1
Øyvind Bråthen
  • 59,338
  • 27
  • 124
  • 151
  • Actually it is NOT called a destructor in C# with good reason. – TomTom Feb 04 '11 at 14:00
  • 16
    Actually **it is**. Thanks for giving me a downvote because you are mistaken. See the MSDN library regarding this specific issue: http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx – Øyvind Bråthen Feb 04 '11 at 14:03
  • 1
    @TomTom it's official name is destructor – David Heffernan Feb 04 '11 at 14:06
  • Its actually not a fallback method, it simply allows the GC to manage when your objects free unmanaged resources, implementing IDisposable allows you to manage that yourself. – HasaniH Feb 04 '11 at 14:12
3

When you have unmanaged resources and you need to make sure they will be cleaned up when your object goes away. Good example would be COM objects or File Handlers.

Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179
1

Destructors provide an implicit way of freeing unmanaged resources encapsulated in your class, they get called when the GC gets around to it and they implicitly call the Finalize method of the base class. If you're using a lot of unmanaged resources it is better to provide an explicit way of freeing those resources via the IDisposable interface. See the C# programming guide: http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx

HasaniH
  • 8,232
  • 6
  • 41
  • 59
-1

Answer: When you have to release unmanaged resources, like file handles, database connections, etc.

// Example
public class Person
{
    private FileStream _fileStream;

    public Person()
    {
        _fileStream = new FileStream("test.txt", FileMode.Open);
    }

    ~Person()
    {
        _fileStream.Close();
    }
}

Explanation: The destructor is called when the object is garbage collected. It is not called when the object is destroyed by the programmer. It is called when the object is no longer referenced by any other object. It is called when the object is no longer in scope. It is called when the object is no longer in memory.