Friday, September 08, 2006

I was recently involved in an ASPAdvice thread about close and dispose - an age old .NET debate. (Okay, the "age old" part is relative.)

As backup, I quoted the msdn documentation that says "close and dispose are functionally equivalent" and someone pointed out not to believe everything I read and that in .NET 1.1, it was known to be "broken".

With a hint from Angel Saenz-Badillos from the ADO.NET team, I opened up reflector to find proof that dispose will close as well . See the guts of dispose and close below.

I don't see anythingn wrong with still calling close *and* dispose, just to be completely explicit. I've seen people do it inside of using blocks with a connection, even though the end of the block will call SqlConnection.Dispose which in turn calls close. So it's redundant. And you would think that C# programmers would celebrate the use of less code.

Are there truly known cases where this fails?

This is SqlConnection's Dispose method:

protected override void Dispose(bool disposing)
{
      if (disposing)
      {
            this._userConnectionOptions = null;
            this._poolGroup = null;
            this.Close();
      }
      this.DisposeMe(disposing);
      base.Dispose(disposing);
}
And just for fun...SqlConnection's Close method. Don't get confused by that Dispose at the end.
That's for a different object, not the actual connection.
 
public override void Close()
{
      IntPtr ptr1;
      Bid.ScopeEnter(out ptr1, "<sc.SqlConnection.Close|API> %d#", this.ObjectID);
      try
      {
            SqlStatistics statistics1 = null;
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                  statistics1 = SqlStatistics.StartTimer(this.Statistics);
                  lock (this.InnerConnection)
                  {
                        this.InnerConnection.CloseConnection(this, this.ConnectionFactory);
                  }
                  if (this.Statistics != null)
                  {
                        ADP.TimerCurrent(out this._statistics._closeTimestamp);
                  }
            }
            catch (OutOfMemoryException exception3)
            {
                  this.Abort(exception3);
                  throw;
            }
            catch (StackOverflowException exception2)
            {
                  this.Abort(exception2);
                  throw;
            }
            catch (ThreadAbortException exception1)
            {
                  this.Abort(exception1);
                  throw;
            }
            finally
            {
                  SqlStatistics.StopTimer(statistics1);
            }
      }
      finally
      {
            SqlDebugContext context1 = this._sdc;
            this._sdc = null;
            Bid.ScopeLeave(ref ptr1);
            if (context1 != null)
            {
                  context1.Dispose();
            }
      }
}
Friday, September 08, 2006 1:21:41 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 
Comments are closed.