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();
}
}
}