Creating a Disposable Class

I am trying to create a class that is disposable and I am not sure that I am doing it correctly.

This class basically is a wrapper to write an event to the event log.

Below is my code.  The code works and my program runs using the class, but I don't know if I did the disposable part correctly.  Basically I don't know if it is really disposing.

public class EventHandle: IDisposable
      {
            private GblVar gv;
                      private bool disposed = false;
            private Component Components;
            public EventHandle(string strLocation, string strEventMessage, System.Diagnostics.EventLogEntryType errorType)
            {
                  try
                  {
                        string strEventText = strLocation + " - " + strEventMessage;

                        System.Diagnostics.EventLog ev = new System.Diagnostics.EventLog();

                        if(!System.Diagnostics.EventLog.SourceExists("AppName"))
                        {
                              System.Diagnostics.EventLog.CreateEventSource(gv.strErrorLogSource, "Application");
                        }

                        ev.Source = gv.strErrorLogSource;
                        ev.WriteEntry(strEventText, errorType);
                        ev = null;
                        strEventText = null;
                  }
                  catch(Exception E)
                  {
                        MessageBox.Show("Error in EventHandle() - " + E.ToString());
                  }
            }            
            #region IDisposable Members

            public void Dispose()
            {
                  GC.SuppressFinalize(this);
            }
            protected virtual void Dispose(bool disposing)
            {
                  // Check to see if Dispose has already been called.
                  if(!this.disposed)
                  {
                        if(disposing)
                        {
                              // Dispose managed resources.
                              Components.Dispose();
                        }
                  }
            }
                  
            #endregion
      }


---------------------------------------------------------

I want to then use it like this.

using(EventHandle evh = new EventHandle("main", "test", System.Diagnostics.EventLogEntryType.Information))
                  {}
LVL 3
gillgatesAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

NipNFriar_TuckCommented:
Hi gillgates, what you have will work... all you HAVE to implement to use the "using" statement is the Dispose() method that is required when you implement the IDisposable interface.  However, after some research we have decided to implement the "Disposable Pattern", which would be done like this...

public class EventHandle: IDisposable
{
   private GblVar gv;
   private bool disposed = false;
   private Component Components;
   public EventHandle(string strLocation, string strEventMessage, System.Diagnostics.EventLogEntryType errorType)
   {
       try
       {
           string strEventText = strLocation + " - " + strEventMessage;

           System.Diagnostics.EventLog ev = new System.Diagnostics.EventLog();

           if(!System.Diagnostics.EventLog.SourceExists("AppName"))
           {
               System.Diagnostics.EventLog.CreateEventSource(gv.strErrorLogSource, "Application");
           }

           ev.Source = gv.strErrorLogSource;
           ev.WriteEntry(strEventText, errorType);
           ev = null;
           strEventText = null;
       }
       catch(Exception E)
       {
           MessageBox.Show("Error in EventHandle() - " + E.ToString());
       }
   }          

    // Implement Finalizer method (destructor equiv in C++)
    ~EventHandler() {
        Dispose( false );
    }
   #region IDisposable Members

   public void Dispose()
   {
       GC.SuppressFinalize(this);
       Dispose( true );
   }
   protected virtual void Dispose(bool disposing)
   {
        // Lock the object... eliminate the posibility of multiple dispose hapenning...
        lock ( this )
        {
           // Check to see if Dispose has already been called.
           if(!this.disposed)
           {
               if(disposing)
               {
                   // Dispose managed resources.
                   Components.Dispose();
                }
           }
       }
   }
               
   #endregion
}

HTH
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
NipNFriar_TuckCommented:
Doh... almost forgot... be sure to set the class variable disposed to true inside the if disposing condition.
0
gillgatesAuthor Commented:
I get an "An unhandled exception of type 'System.NullReferenceException' occurred in app.exe    Additional information: Object reference not set to an instance of an object."

On this line...

Components.Dispose();
0
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

NipNFriar_TuckCommented:
Ah... I normally will chack an object before disposing it to keep this from happening like:

if ( Components != null  && Components.Count > 0 ) {
    Components.Dispose();
}
0
Razzie_Commented:
Do you really want to implement IDisposable for this class? There is no gain in implementing it if your class will not use unmanaged resources. For example, since the Components collection will always be null.

Being able to use a using statement is nice, granted, since it looks clean. However, performance / memory wise you will have no use for it. I can imagine it could even mean a performance hit. It will have to run through the whole Dispose() method while there's absolutely nothing happening.

Regards,

Razzie
0
gillgatesAuthor Commented:
Razzie

So if I don't make it disposable, then what do I do with the object when I am done using it?  Just set it to null?
0
Razzie_Commented:
If you use it only in the scope of the method, that is not even necessary. You can simply let it be and it will be garbage collected. If it is a global object, you could set it to null.

private void someMethod()
{
   MyObject myObject = new MyObject();
   // Do stuff here
   ....
   // Do more stuff
}

In the above code, it will get garbage collected. In most cases, you don't have to set it to null.

class MyClass
{
   private MyObject myObject;

   private void someMethod()
   {
      this.myObject = new MyObject();
      // Do stuff here
      ...
      this.myObject = null;
   }
}

In the above, you could set it to null if you won't need the instance of MyObject anymore in the rest of your program.

HTH,

Razzie

0
NipNFriar_TuckCommented:
What Razzie says is true, however there are circumstances that you need to be aware of...

1) If you use unmanaged resources you need to clean these up.  (Razzie statied this earlier).
a) If you use database connections, datareaders, etc... these need to be cleaned up as you can end up with a defunc connection for a period of time if you do not...
b) If you open stream of any sort... these need to be cleaned up.

Even if you are using the DotNET classes for the stream or db classes you should make sure you close/dipose of these particular classes.  Consequently, if you are using the resources at the class level you will probably want to implement the IDisposable with the Disposable Pattern; for local resources you can use a try{ } catch { } finally { // Do clean up here } type of construct.
0
Razzie_Commented:
That is true, unless you use your streams or conncetion within a using clause already:

class MyClass
{

   private void someMethod()
   {
      using(StreamReader sr = new StreamReader())
      {
          // code
      }
   }
}


In the above example, there is no need to implement IDisposable, since the using clause is compiled to a try - finally, calling the Dispose() method in the finally block.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.