2

I have some files written to a temp location in c#. They are then rendered as pdf thumbnails. When the object is destroyed i want the location cleaned up so is it ok in this instance to use a deconstructor?

    ~Foo()
    {
        try
        {
            Directory.Delete(path, true);
        }
        catch (IOException ex)
        {
            Console.WriteLine("exception: " + ex.Message + " . from: Foo_Closing");
        }
ricki
  • 149
  • 1
  • 3
  • 10

8 Answers8

7

Even though it has the same syntax as a C++ destructor this a finalizer in C# which runs when the object is garbage collected at finalization - this will have a performance impact since the GC has to run a separate thread to run all finalizers, to do this your object instance will live longer than neccessary.

Having said that you should not use it if you do not absolutely have to - an exception is when you have to dispose of resources, in which case your class should also implement IDisposable. This would allow consumers of your class to wrap it in a using block, which will call Dispose() - that is where you should tear down resources.

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
  • the above wasnt meant rudley btw :) you just told me what i shouldnt do at the time . – ricki Apr 07 '11 at 13:31
  • @ricki: Understood - I added to my answer: Implement `IDisposable` and dispose of resources there - use a `using` block when instantiating your class, also call `Dispose()` in your finalizer. If possible delete temp folder earlier or use system temp folder – BrokenGlass Apr 07 '11 at 13:35
3

You should implement the IDisposable interface, and do your cleanup in there.

Nils Magne Lunde
  • 1,794
  • 1
  • 13
  • 21
3

The problem with deconstructors (aka destructors or finalizers) is that you can't predict when they will run, since they are called by the garbage collector. In order to have a predictable behavior, you should implement IDisposable and call Dispose explicitly (or use the object in a using block)

You can also call Dispose from the destructor in case it was not called explicitly. See this page for the recommended pattern to use.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • +1 for using - probably worth pointing out that implementing IDisposable properly can be slightly tricky and that disposable members mean the containing class needs to be disposable (which makes disposable members a bit of a headache) – jk. Apr 07 '11 at 13:29
2

I'd probably just use the environment's temporary file/folder locations so that the files can be cleaned up by a user or administrator as part of the normal housekeeping process.

Don't bother doing this as it smacks of a hack - is it really that important that the folders are deleted there and then?

Andras Zoltan
  • 41,961
  • 13
  • 104
  • 160
  • yes because - for a particular search i only want the returned pdfs displayed, if i wait for a user to clean up then the folder will be populated with old contents and new – ricki Apr 07 '11 at 13:24
  • Could you clean up the folder _before_ you make a search? – John Källén Apr 07 '11 at 13:26
2

Avoid implementing finalzers of at all possible. You don't control when they get called, and they cause performance loss as the runtime needs to treat objects with finalizers specially. In general, you should only implement a finalizer if you have a native object handle or other native resource that needs to be cleaned up.

Instead, implement the IDisposable interface on your class, move your cleanup code to the Dispose method, and make sure all your clients call the Dispose method (the using statement is handy for this purpose).

John Källén
  • 7,551
  • 31
  • 64
2

Implement the IDisposable Interface istead:

public class tester : IDisposable
{
    #region IDisposable Members

    public void Dispose()
    {
        //cleanup code here
    }

    #endregion
}

using (tester t = new tester())
{

}
//tester now disposed 

But don't forget this gem of knowledge from MSDN:

Because the Dispose method must be called explicitly, objects that implement IDisposable must also implement a finalizer to handle freeing resources when Dispose is not called

So, you should also implement you finalizer as well as your IDisposable interface, bearing in mind that both will be called.

James Wiseman
  • 29,946
  • 17
  • 95
  • 158
  • But the "freeing resources" here refers to native resources, like HANDLEs to opened files and the like, doesn't it? Externalities like files in the file system, which aren't opened in your code, don't apply as "resources" in this context. – John Källén Apr 07 '11 at 13:58
  • The term "resources" is a bit unclear. A resource isn't a "thing"--it's a responsibility which only some particular object has the information and impetus to carry out. The creation of a file which is supposed to be deleted before a program exits is such a responsibility; I'd be a little leery of a little leery of deleting files within a Finalize method (what C# annoyingly calls a "destructor"), though, since various factors may cause such operations to fail or be blocked for an arbitrarily long time. Note also that finalizers can sometimes run before they're expected to, causing trouble. – supercat Apr 11 '11 at 22:21
1

why not use IDisposable inteface instead and then you can wrap your call with "using" and Dispose() will perform all the clean up it needs to perform

public class Foo : IDisposable { public void Dispose() { //Clean up here}
}

using (foo = new Foo() ) { //consume foo here }

Bek Raupov
  • 3,782
  • 3
  • 24
  • 42
0

There is an option to delete temp files on close, if you are able to leverage that it doesn't matter right? Try these links

  1. Handling with temporary file stream
  2. http://msdn.microsoft.com/en-us/library/system.io.fileoptions.aspx
  3. http://www.codeproject.com/KB/system/Taking_care_of_temp_files.aspx?msg=3489384
Community
  • 1
  • 1
Anuraj
  • 18,859
  • 7
  • 53
  • 79