Using, using, using with C# 8

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.

Emotions

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 Disposeis 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.

Buy Me A Coffee

Interesting Links for this article:

Complete code sample

Other C# 8 articles:

Async Streams with C# 8

C# 8 Proposal for Async Streams

Proposal: IAsyncEnumerable.WithCancellation Extension Method

C# 8: Indexes and Ranges

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

Advertisement

13 thoughts on “Using, using, using with C# 8

    1. 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.

      Like

      1. 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.

        Like

      2. 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.

        Like

    2. 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?

      Like

  1. 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).

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.