none
Disposable class with base class constructor exception? RRS feed

  • Question

  • Hi!

    Given this bit of code:

    using System;
    using System.IO;
    using System.Threading;
    
    namespace ConsoleApplication9
    	{
    	public class Base
    		{
    		public Base(string DirName)
    			{
    			DirectoryInfo Dir = new DirectoryInfo(DirName);
    			}
    		}
    
    	public class Kid : Base, IDisposable
    		{
    		public Kid(string FileName)
    			: base(Path.GetDirectoryName(FileName))
    			{
    			// How can I call Dispose here when Base or Path.GetDirectory throw?
    			}
    		
    		public readonly ManualResetEventSlim Finished=new ManualResetEventSlim();
    		
    		public void Dispose()
    			{
    			// I know, there's a proper pattern with a protected function, never mind.
    			Finished.Dispose();
    			}
    		}
    
    	class Program
    		{
    		static void Main(string[] args)
    			{
    			Kid K;
    			try
    				{
    				K=new Kid(null);
    				}
    			catch
    				{
    				// K is unassigned here!
    				K.Dispose();
    				}
    			// This one aborts with "unhandled exception"
    			using (Kid L = new Kid(null))
    				{
    				}
    			}
    		}
    	}
    

    how does one protect against the exception in the base class?

    At some point I need to dispose of the "Finished" Semaphore.

    Lots of Greetings!

    Wednesday, February 20, 2013 5:24 PM

Answers

  • The solution is to move your ManualResetEvent initialization from variable level to constructor, like this:

    public Kid(string FileName) : base(Path.GetDirectoryName(FileName))
    {
        Finished = new ManualResetEventSlim();
    }
    		
    public readonly ManualResetEventSlim Finished;

    The reason of problem in your code is variable initializers run before base constructors, so if base constructor fails, you already have initialized (and undisposed) event.

    If you rewrite the code as above, event will be initialized after base constructor successfully finished, so there's no problem with disposing.

    Also, sometimes it is reasonable to implement a finalizer in your class.

    • Proposed as answer by Miha Markic Thursday, February 21, 2013 11:31 AM
    • Marked as answer by v_he Thursday, February 21, 2013 12:14 PM
    Wednesday, February 20, 2013 9:28 PM

All replies

  • A couple of things,

    The base class should be designed like another other class to handle exceptions. If you base  class throws an exception during initialization it should clean up it's own resources that need to be cleaned up. Since your base doesn't implement IDisposable it doesn't seem like there's anything to Dispose anyway. 

    Remember that IDisposable should only be implemented if there's unmanaged resources to dispose of as per the remarks section in the MSDN Help:

    MSDN IDisposable

    Wednesday, February 20, 2013 8:48 PM
  • The solution is to move your ManualResetEvent initialization from variable level to constructor, like this:

    public Kid(string FileName) : base(Path.GetDirectoryName(FileName))
    {
        Finished = new ManualResetEventSlim();
    }
    		
    public readonly ManualResetEventSlim Finished;

    The reason of problem in your code is variable initializers run before base constructors, so if base constructor fails, you already have initialized (and undisposed) event.

    If you rewrite the code as above, event will be initialized after base constructor successfully finished, so there's no problem with disposing.

    Also, sometimes it is reasonable to implement a finalizer in your class.

    • Proposed as answer by Miha Markic Thursday, February 21, 2013 11:31 AM
    • Marked as answer by v_he Thursday, February 21, 2013 12:14 PM
    Wednesday, February 20, 2013 9:28 PM
  • Just a remark on finalizer. As Pantelis44999 said, finalizer should only be used when dealing with unmanaged resources that need cleaning.

    Miha Markic [MVP C#] http://blog.rthand.com

    Thursday, February 21, 2013 11:32 AM