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(); } } }
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(); } } }
See my speaking schedule for more events
User Group Leader
Hosted by:
Powered by: newtelligence dasBlog 2.0.7226.0
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2008, Julie Lerman
E-mail