Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I implement IDisposable when class has IDisposable member but no unmanaged resources?

Tags:

c#

.net

The MSDN documentation and many answers here on StackOverflow go to lengths to disucss correctly implementing IDisposable, e.g. MSDN IDisposable, MSDN Implementing IDisposable, An excellent StackOverflow Q&A

However none of them seem to cover a more common use-case I have: what to do when my class has an IDisposable member that lives longer than one method? For example

  class FantasticFileService   {     private FileSystemWatcher fileWatch; // FileSystemWatcher is IDisposable      public FantasticFileService(string path)     {       fileWatch = new FileSystemWatcher(path);       fileWatch.Changed += OnFileChanged;     }      private void OnFileChanged(object sender, FileSystemEventArgs e)     {       // blah blah     }   } 

The closest MSDN gets to addressing this problem only covers the use-case when the instance of IDisposable is short lived so says call Dispose e.g. by using using:

Implement IDisposable only if you are using unmanaged resources directly. If your app simply uses an object that implements IDisposable, don't provide an IDisposable implementation. Instead, you should call the object's IDisposable.Dispose implementation when you are finished using it.

of course that is not possible here where we need the instance to survive longer than a method call!?

I suspect the correct way to do this would be to implement IDisposable (passing the responsibility to creator of my class to dispose it) but without all finalizer and protected virtual void Dispose(bool disposing) logic becuase I don't have any unmanged resources, i.e.:

  class FantasticFileService : IDisposable   {     private FileSystemWatcher fileWatch; // FileSystemWatcher is IDisposable      public FantasticFileService(string watch)     {       fileWatch = new FileSystemWatcher(watch);       fileWatch.Changed += OnFileChanged;     }      public void Dispose()     {       fileWatch.Dispose();     }   } 

But why is this use-case not explicitly covered in any official documentation? And the fact it explicitly says do not implement IDisposable if your class does not have unmanaged resources makes me hesitant to do so... What is a poor programmer to do?

like image 935
markmnl Avatar asked Jun 21 '16 01:06

markmnl


People also ask

When should you use IDisposable?

If you access unmanaged resources (e.g. files, database connections etc.) in a class, you should implement IDisposable and overwrite the Dispose method to allow you to control when the memory is freed.

Which of these are the reason for implementing IDisposable interface?

If your class creates unmanaged resources, then you can implement IDisposable so that these resources will be cleaned up properly when the object is disposed of. You override Dispose and release them there.

What happens if you dont Dispose IDisposable?

IDisposable is usually used when a class has some expensive or unmanaged resources allocated which need to be released after their usage. Not disposing an object can lead to memory leaks.

How do you know if a class implements IDisposable?

If a type implements the IDisposable interface, you should always call the Dispose method on an instance of the class when you are done using it. The presence of IDisposable indicates that the class has some resources that can be released prior to garbage collection.


1 Answers

It looks like your case is indeed covered by some documentation, namely the design warning CA1001: Types that own disposable fields should be disposable.

That link has an example of what your IDisposable implementation should look like. It will be something like as follows. Eventual design guidelines can be found at CA1063: Implement IDisposable correctly.

  class FantasticFileService : IDisposable   {     private FileSystemWatcher fileWatch; // FileSystemWatcher is IDisposable      public FantasticFileService(string watch)     {       fileWatch = new FileSystemWatcher(watch);       fileWatch.Changed += OnFileChanged;     }      ~FantasticFileService()     {       Dispose(false);     }      protected virtual void Dispose(bool disposing)     {       if (disposing && fileWatch != null)       {         fileWatch.Dispose();         fileWatch = null;       }     }      public void Dispose()     {       Dispose(true);       GC.SuppressFinalize(this);     }   } 
like image 110
gnalck Avatar answered Sep 20 '22 08:09

gnalck