The Behavior of a Using Statement
14 November, 2008 § Leave a comment
C# comes right out of the box with it’s own garbage collector. When objects are no longer referenced and go out of scope, they are then marked for garbage collection. Some of these objects may have special properties.
They may carry handles to files, connections to databases, etc. When the garbage collector picks these objects up, it doesn’t really know what to do with these associations.
Cleverly, there is an interface to solve this. It’s called IDisposable. With IDisposable, you are required to implement one function, Dispose(). Dispose can be compared to the C++ destructor. File buffers and database connections can all be closed right within Dispose.
This seems nice, but awkward to call Dispose on an object when you are done with it. It would be nice to just nest that object in a block statement so it is easier to see from a glance when a specific object is not needed. It would also be nice if that Dispose method could be called when the block is finished.
This brings us towards a using statement. Here is an example:
ResultSet resultSet; using( var sqlConnection = new SqlConnection() ) { resultSet = sqlConnection.ExecuteQuery( "select * from `products`" ); sqlConnection.ExecuteNonQuery( "delete from `products`" ); } ... ... //messing around with the result set ... return resultSet;
When the using statement is finished, the Dispose method is called automatically, closing the connection to the database. This is better than just writing the following:
var sqlConnection = new SqlConnection(); ResultSet resultSet = sqlConnection.ExecuteQuery( "select * from `products`" ); sqlConnection.ExecuteNonQuery( "delete from `products`" ); sqlConnection.Dispose(); ... ... //messing around with the result set ... return resultSet;
In the first example the connection is guaranteed to be closed. The second example leaves open the possiblity that it won’t be closed. If an exception is thrown by the SqlConnection, let’s say in the constructor or when it’s trying to execute one of the queries, the code will never execute the Dispose statement.
How does this work?
Effectively, a using statement is really a fancy name for a try-finally. You can rewrite the first example and get the same benefits as follows:
ResultSet resultSet; SqlConnection sqlConnection; try { sqlConnection = new SqlConnection(); resultSet = sqlConnection.ExecuteQuery( "select * from `products`" ); sqlConnection.ExecuteNonQuery( "delete from `products`" ); } finally { sqlConnection.Dispose(); } ... ... //messing around with the result set ... return resultSet;
I hope that better explains using statements, and their purpose.
Leave a Reply