C# has different meanings for the using keyword. One is the using directive to import types from namespaces, and to create aliases to types. The second meaning is the using statement as a convenient syntax on using the IDisposable interface. With C# 6, also the using static directive was added to allow accessing static class members without the need to specify the type. C# 8 now adds another variant to the using keyword – one that is related with the using statement, the using declaration. I think I will replace most of my usages of the using statement to use the new using declaration instead. This article does not step into the using directive, but gives you information about the new C# 8 feature using declaration.
Disposing Resources
First, let’s start with the traditional using statement and the class AResource
which implements the IDisposable
interface:
public class AResource : IDisposable { public void UseIt() => Console.WriteLine($"{nameof(UseIt)}"); public void Dispose() => Console.WriteLine($"Dispose {nameof(AResource)}"); }
The using statement can be used to reference a variable or the result from a method, and at the end of the scope defined by the using statement, the Dispose
method gets invoked:
private static void TraditionalUsingStatement() { using (var r = new AResource()) { r.UseIt(); } // r.Dipose is called }
Behind the scenes, the compiler creates code using try/finally to make sure Dispose
is also called when an exception is thrown:
private static void TraditionalUsingStatementExpanded() { var r = new AResource(); try { r.UseIt(); } finally { r.Dispose(); } }
With the new C# 8 using declaration, the code with the using statement can be simplified. Curly brackets are no longer needed. At the end of the scope of the variable r (which is here the end of the method), the Dispose
method is invoked. Here, the compiler also creates a *try/finally block to make sure Dispose
is called if errors occur.
private static void NewWithUsingDeclaration() { using var r = new AResource(); r.UseIt(); }
That’s a small feature of C# 8, but we need to get a little bit more into details.
Disposing Multiple Resources
Using multiple resources, I’ve often seen code like this with multiple nested using statements:
private static void TraditionalMultipleUsingStatements() { using (var r1 = new AResource()) { using (var r2 = new AResource()) { r1.UseIt(); r2.UseIt(); } } }
Because the body of the outer using statement just consists of a single statement – the inner using statement, it is possible to simplify the code. This looks better than the previous one, and it stays better also if more than two resources need to be disposed:
private static void TraditionalMultipleUsingStatements2() { using (var r1 = new AResource()) using (var r2 = new AResource()) { r1.UseIt(); r2.UseIt(); } }
Next let’s do the same with the new using declaration. The following code is even shorter compared to the previous one – no matter how many resources you need to dispose:
private static void NewMultipleUsingDeclarations() { using var r1 = new AResource(); using var r2 = new AResource(); r1.UseIt(); r2.UseIt(); }
Using Scopes
What if a resource should be disposed before the method ends? You just need to add a separate scope using curly brackets. When the variable is out of scope, the resource is disposed:
private static void UsingDeclarationWithScope() { { using var r1 = new AResource(); r1.UseIt(); } // r1 is disposed here! Console.WriteLine("r1 is already disposed"); }
What can’t be done with the using declaration
Is there a reason to not use the using declaration, and keep the using statement?
In case you’ve a method returning a disposable, such as the method GetTheResource
,
public static AResource GetTheResource() => new AResource();
and you don’t need a variable of this type, you just need to make sure the resource returned is disposed – with the using statement this code is possible:
private static void TraditionalResourceReturned() { using (GetTheResource()) { // do something here } // resource is disposed here }
If you try to do the same with the using declaration, you’ll get multiple compilation errors – all in the same code line:
private static void NewResourceReturned() { using GetTheResource(); // do something here } // resource is disposed here
- CS1001: Identifier expected
- CS1528: Expected ; or = (cannot specify constructor arguments in declaration)
- CS1003: Syntax error, ‘[‘ expected
- CS1003: Syntax error, ‘]’ expected
Probably a future version of the compiler results in a different compiler error.
The reason is that the using declaration requires a variable for the scope. In case you don’t need the variable afterwards, there’s an easy fix – just use _
for the variable name, and ignore it:
private static void NewResourceReturned() { using var _ = GetTheResource(); // do something here } // resource is disposed here
Summary
It’s just a small feature of C# 8, but it will change the code in many places. Currently I don’t see a reason to stay with the old using statement. I think I’ll switch to the new using declaration with all my code. The number of curly brackets are reduced, but it can still be seen easily where a resource is disposed. The number of code lines is reduced using the name using declaration.
If you’ve read this far, consider buying me a coffee which helps me staying up longer and writing more articles.
Interesting Links for this article:
Other C# 8 articles:
C# 8 Proposal for Async Streams
Proposal: IAsyncEnumerable.WithCancellation Extension Method
C# 8: Pattern matching extended
C# 8: No more NullReferenceExceptions – What about legacy code?
More information on C# and programming .NET Core applications is in my book Professional C# 7 and .NET Core 2.0, and in my workshops.
Enjoy learning and programming!
Christian
Why do we even need to use the using keyword in front of a var for IDisposable? This should be automatic.
LikeLiked by 1 person
Pete, this could be a good idea. However, this would also be a breaking change. I think, I prefer seeing Dispose to be called – which happens using both the using statement and the using declaration.
LikeLike
I don’t follow, why is it a breaking change?
Using becomes redundant / optional, but still works fine (or can be made to work fine even with the automatic call to Dispose).
If someone’s implementing IDisposable, then it better be for the purpose of clean-up when the var goes out of scope and not just as a function they want to manually call.
LikeLike
Pete, I’m sure this would not be an issue in my code. But I’m relatively sure it’s an issue with some code somewhere when Dispose is automatically called while it is not called today. The C# team is very careful with breaking changes. However, you could submit a feature request to the C# language repository, then we know for sure.
LikeLike
This doesn’t make sense Pete.
If that was the case, then how could you ever return IDisposable object from a function, if using ‘var’ to create it would result in disposing of this object before it’s returned?
Would you make ‘return new Disposable()’ behave differently from ‘var item = new Disposable(); return item’ and somehow force people to only create the disposable item as the last operation in the function?
LikeLike
Interesting! At least at first glance, this looks very handy 🙂
LikeLike
Personally, I don’t really like this style. I want my variables to dispose as soon as possible and not wait until the end of the method. If you have multiple disposes and you want them closed as soon as possible, it looks much cleaner with the using { } than just having random { } first in the middle. It actually makes it take more lines (assuming the disposes aren’t inside of each other).
LikeLike