Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with exceptions in constructor when implementing IDisposable

Tags:

c#

idisposable

I read I need to implement IDisposable if my class has a member variable that is itself IDisposable. Well, I am implementing IDisposable interface because my class contains a database object (db class member below) which is IDisposable itself:

    public class CommissionModel : IDisposable
    {
        protected PetaPoco.Database db;

        public CommissionModel()
        {
            string connectionString = "Server=localhost;...";

            // The line below may throw an exception (!!!)
            db = new PetaPoco.Database(connectionString, "mysql");              
        }

        // Automatically close database connection
        public void Dispose()
        {
            if (db != null)
                db.Dispose();

            db = null;
        }

        public void InsertRecord(Record somerecord)
        {
            // ...
            db.Insert(somerecord);
        }

The problem is instantiation of db member may fail under some circumstances. What should I do when the exception is thrown in the constructor and the database object gets not created? Should I rethrow the exception or maybe check if db != null in InsertRecord method?

like image 806
ezpresso Avatar asked Dec 15 '11 21:12

ezpresso


People also ask

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.

Does not implement IDisposable Dispose?

If an object doesn't implement IDisposable , then you don't have to dispose of it. An object will only expose Dispose if it needs to be disposed of.

What does it mean when an object implements IDisposable?

Typically, types that use unmanaged resources implement the IDisposable or IAsyncDisposable interface to allow the unmanaged resources to be reclaimed. When you finish using an object that implements IDisposable, you call the object's Dispose or DisposeAsync implementation to explicitly perform cleanup.

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.


4 Answers

If your constructor throws an exception, the consumer of your code will never receive a reference to an instance of your class. The partially initialized class memory will eventually be collected and Dispose will not be called.

I would generally recommend moving an operation that can fail due to outside circumstances (and not due to misusage, like an invalid parameter value) to a separate method, like "Connect".

like image 83
Dan Bryant Avatar answered Sep 23 '22 02:09

Dan Bryant


Ideally you should not be doing any "work" in the constructor. Work in the constructor should really be linking up object references. This would allow you to unit test this class by hooking up mock classes instead.

Try this instead:

public CommissionModel(PetaPoco.Database db) {
    this.db = db;
}
like image 29
Andy Christianson Avatar answered Sep 24 '22 02:09

Andy Christianson


It looks like you don't have to do anything.

If your construction process is interrupted the resource is not created. In most usage scenarios (this lays outside your class), the Dispose() will never be called. But even when it is, your if (db != null) code is enough of a guard.

A few minor points:

  • the db = null; inside Dispose() is pointless.
  • InsertRecord() should start by checking if (db != null)
like image 23
Henk Holterman Avatar answered Sep 23 '22 02:09

Henk Holterman


You should only catch exceptions that you can handle. From the code, it appears that initializing the variable db may show that there is a problem communicating with your database server.

My suggestion is to leave your code as is and handle exceptions in a central location such as the Application_Error event in the Global.asax or the event that is initializing the CommissionModel.

like image 35
Novus Avatar answered Sep 25 '22 02:09

Novus