Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to dispose C# base class when derived class constructor generates an error

If a C# derived IDisposable class constructor generates an error, how to dispose of the already fully constructed IDisposable base class?

Since all fields in the class hierarchy are initialized before any constructor executes, is it safe for the derived constructor to call base.Dispose()? It violates the rule of not calling virtual methods until object is fully constructed, but I can't think of another way to do it, and my searching hasn't turned up anything about this scenario.

like image 963
jimvfr Avatar asked Jan 17 '13 01:01

jimvfr


People also ask

What is Dispose () in C#?

The Dispose method performs all object cleanup, so the garbage collector no longer needs to call the objects' Object. Finalize override. Therefore, the call to the SuppressFinalize method prevents the garbage collector from running the finalizer. If the type has no finalizer, the call to GC.

Is Dispose called automatically C#?

Dispose() will not be called automatically. If there is a finalizer it will be called automatically. Implementing IDisposable provides a way for users of your class to release resources early, instead of waiting for the garbage collector.

How do you Dispose a variable in C#?

To free and reset the resources that are unmanaged like connections to the databases, files, etc., and to perform a cleanup of the memory, we make use of a function called dispose of () function in C#. The dispose() function in C# must implement the IDisposable interface.

What is the use of Dispose method in C# with example?

As an example, consider a class that holds a database connection instance. A developer can call Dispose on an instance of this class to release the memory resource held by the database connection object. After it is freed, the Finalize method can be called when the class instance needs to be released from the memory.


2 Answers

My view is that constructors should be light, not relying on external resources/etc that might throw an exception. The constructor should do enough to verify Dispose() can be safely called. Consider using containment instead of inheritance, or having a factory method do the work that might throw.

like image 140
Frank Schwieterman Avatar answered Oct 13 '22 20:10

Frank Schwieterman


All derived class constructors must call Dispose on the object being constructed if they exit via an exception. Further, it's very difficult to write leak-proof classes if field initializers construct IDisposable instances or can fail. Too bad, since requiring objects to be declared in one place, initialized in a second, and cleaned up in a third is not exactly a recipe for coherent code.

I would suggest that the best pattern is probably something like:

class foo : baseFoo , IDisposable
{
    foo () : baseFoo
    {
        bool ok = false;
        try
        {
            do_stuff();
            ok = true; // Only after last thing that can cause failure
        }
        finally
        {
            if (!ok)
              Dispose();
        }
    }
}

Note that C++/CLI automatically implements that pattern, and can also automatically handle cleanup of IDisposable fields. Too bad the language seems like a pain in other ways.

PS--With relatively few exceptions, mostly revolving around predictable-cost shared immutable objects (e.g. brushes, fonts, small bitmaps, etc.), code which relies upon Finalize to clean up objects is broken. If an IDisposable is created, it must be disposed unless the code which created it has particular knowledge about the consequences of deferring disposal to a finalizer.

like image 23
supercat Avatar answered Oct 13 '22 21:10

supercat