Since its release on C# 8.0 in September 2019, using
declarations became the most common way to initialize disposable objects, even being the default suggestion if you’re using Rider with Resharper. Whereas before we would wrap the code within a block, we can now just prefix our variable declaration with using
.
I know that this is not a trending topic, but I always find it helpful to read different explanations of the same subject when I'm trying to understand something.
Using statement:
using (var connection = new SqlConnection(connectionString))
{
...
}
Using declaration:
using var connection = new SqlConnection(connectionString);
What exactly does “using” do with our variable?
Whether you chose the classic approach (using statement) or using declaration, the end goal is to explicitly dispose your variable, without relying on the Garbage Collector. Something you could also achieve by doing this:
var connection = new SqlConnection(connectionString);
connection.Dispose();
Besides syntax, is there any other difference between those approaches?
Yes. The difference is in the scope!
With the using
statement, you’re delimitating the scope of your variable. It gets initialized when you open the block and disposed when you close it. Simple and readable, right? Here's an example of the variable not being available anymore once its code block is closed:
static void TestDbConnectionWithUsingStatementIncorrectScope()
{
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(commandText, connection))
{
command.Connection.Open();
command.ExecuteNonQuery();
}
}
using (var command2 = new SqlCommand(commandText2, connection))
{
// Compilation error.
// The connection object isn't available
// anymore as it has already been disposed.
}
}
But how does the Compiler know when to dispose your variable if you just added a using declaration, without defining a block? The compiler will dispose your variable at the end of its current code block when it’s not usable anymore.
static void TestDbConnectionWithUsingDeclaration()
{
using var connection = new SqlConnection(connectionString);
using var command = new SqlCommand(commandText, connection);
command.Connection.Open();
command.ExecuteNonQuery();
using var command2 = new SqlCommand(commandText2, connection);
} // Code compiles successfully as all objects
// will be disposed at this block end
The same could be correctly implemented with using statement. With more lines of code and more code blocks than on the previous version:
static void TestDbConnectionWithUsingStatement()
{
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(commandText, connection))
{
command.Connection.Open();
command.ExecuteNonQuery();
}
using (var command2 = new SqlCommand(commandText2, connection))
{
}
}
}
It could also be done by explicitly calling the Dispose Method. The disadvantage is that you might forget to dispose one of your objects, and it's not as readable as the previous versions, depending on how many lines of code you have in your Method:
static void TestDbConnectionWithDispose()
{
var connection = new SqlConnection(connectionString);
var command = new SqlCommand(commandText, connection);
command.Connection.Open();
command.ExecuteNonQuery();
var command2 = new SqlCommand(commandText2, connection);
connection.Dispose();
command.Dispose();
command2.Dispose();
}
Conclusion: What should I use?
That depends. If you want to decrease the number of scope blocks in your code, go for the using
declaration approach. In some specific cases though, where you don’t want your variable to be available in the whole context of your current block (maybe you’re dealing with a big Method in a Legacy application), you’d rather use the using
statement, explicitly defining when your variable should live.
Top comments (3)
Hello, just a a note here. The two forms are statements. One is a block statement and the other is a line statement. Do you know there is a using declaration too? The one that says the namespaces you are using.
using declaration is how Microsoft named the feature in C# 8.0. The using declaration you refer to is the using directive, to use types from namespaces and define aliases: learn.microsoft.com/en-us/dotnet/c..., not related to my post as I'm more focused on scoping disposable variables.
Thanks for your comment.
Hmm, I see. I've keep calling them declarations for years. Directives. OK. Thanks for the note!