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