Dispose and Finalize methods

Here are are few tips on using the IDisposable pattern and using Finalizers

  • Implement IDiposable if accessing managed resources like SQLConnection/Command objects and not disposing them from within the method which instantiates the managed resource

  • Implement Finalizer only if using unmanaged resources (Files, Streams, Windows Handles, Pinvoke) and not disposing them from with the method that instantiates the unmanaged resources

  • Insure that each Type that has a finalizer is responsible for disposing only 1 unmanaged resource, and never reference “reference types” from within a Finalizer

  • Use a protected “disposed” bool within a IDiposable type and check its value in the beginning of each method of that type

  • If a type has a “Open” method which opens a managed resource, then insure that you Implement a Close() method which calls the explicit implementation of IDisposable.Dispose() method

1: public class EncryptedStream : IDisposable

2: {

3: public void Close()

4: {

5: (this as IDisposable).Dispose();

6: }

7: 

8: void IDisposable.Dispose()

9: {

10: //Release resources

11: }

12: }

  • If the Dispose() method can be called from multiple threads then insure that you use lock(this) before releasing resources. Here is a correct implementation of IDisposable and Finalize pattern which has unmanaged and managed resources to release:

1: public class DisposeType : IDisposable

2: {

3: protected bool disposed;

4: //insure the access modifier is protected so that derived classes can also make use of the same

5: protected virtual void Dispose(bool disposing)

6: {

7: if (disposed)

8: return;

9: 

10: lock (this)

11: {

12: if (disposing)

13: {

14: // Release Managed resources here

15: }

16: // Release UnManaged resources here

17: //call the base object's Dispose protected method

18: base.Dispose(disposing);

19: disposed = true;

20: }

21: }

22: 

23: public void Dispose()

24: {

25: Dispose(true);

26: GC.SuppressFinalize(this);

27: }

28: 

29: ~DisposeType()

30: {

31: Dispose(false);

32: }

33: }

  • Compound Finalizable objects: If you have a finalizable object that occupies lot of memory then consider splitting it into 2 classes, one that contains the finalizable object and other that contains the high memory using variables:

1: public class CompoundObject : IDisposable

2: {

3: //this array takes lot of memory

4: int[] array;

5: //instance of inner finalizable object

6: ClipBoardWrapper cwrapper;

7: 

8: public CompoundObject(int hwnd, int elements)

9: {

10: array = new int[elements];

11: cwrapper = new ClipBoardWrapper(hwnd);

12: }

13: 

14: public void Dispose()

15: {

16: cwrapper.Dispose();

17: }

18: 

19: private class ClipBoardWrapper : IDisposable

20: {

21: [System.Runtime.InteropServices.DllImport("user32")]

22: private static extern int OpenClipboard(int hwnd);

23: 

24: [System.Runtime.InteropServices.DllImport("user32")]

25: private static extern int CloseClipboard();

26:

27: public ClipBoardWrapper(int hwnd)

28: {

29: OpenClipboard(hwnd);

30: }

31:

32: public void Dispose()

33: {

34: CloseClipboard();

35: GC.SuppressFinalize(this);

36: }

37: ~ClipBoardWrapper()

38: {

39: Dispose();

40: }

41: 

42: }

43: }

This article is part of the GWB Archives. Original Author: Rohit Gupta

New on Geeks with Blogs

  • We Won The One Award I Actually Care About

    Full Scale made the Inc. 5000 for the fifth year straight, the 12th listing across my three companies. Here is why the one award you cannot buy is worth stopping for.

  • Your Customers Build the Features Now

    I let a tool I liked sit dead for a year rather than build the features I wanted. An MCP server meant I never had to, and your customers can do the same to your product.

  • Get the Size of a Directory in Linux the Easy Way

    du -sh for the quick answer, ncdu for the cleanup, df for the disk itself: every command for checking directory size in Linux, plus why du and df never agree.

  • Vim Search and Replace: The Ultimate Guide

    One :%s command replaces every match in a file before a find dialog would even open. The Vim substitute patterns worth the muscle memory: flags, ranges, capture groups, and multi-file edits.