Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 397
  • Last Modified:

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))
                  {}
0
gillgates
Asked:
gillgates
  • 4
  • 3
  • 2
2 Solutions
 
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
 
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
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

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now