C# 8 – Making Use of Using Declarations

October 09, 2020
Written by
Dustin Ewers
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by
AJ Saulsberry
Contributor
Opinions expressed by Twilio contributors are their own

csharp-8-using-statements.png

With C# 9 just around the corner, it’s a good time to look back at some of the goodness in C# 8. This post will take a look at a little syntactic sugar known as using declarations.

Since time immemorial, C# programmers have been using the using statement to implement disposable classes safely. File I/O, databases, and web services all benefit from the using statement.

The only downside is that adding a using statement to your code introduces a new scope block and indentation level. C# 8 using declarations eliminate that requirement.

Review: the using keyword

In C#, the using keyword has two purposes: The first is the using directive, which is used to import namespaces at the top of a code file. The second is the using statement. C# 8 using statements ensure that classes that implement the IDisposable interface call their dispose method. It guarantees that the dispose method will be called, even if the code throws an exception.

This guarantee is essential when the disposable object references lockable or finite resources like files and network connections. You don’t want your code locking resources up indefinitely because it blew up while trying to use that resource.

The following code is an example of the using statement in action. To run this code, spin up a new console app in Visual Studio 2019 or Visual Studio Code.

Or you can use an online IDE and copy this code into it. .NET Fiddle is nice for playing with new features and trying out code snippets, but be sure to set the Compiler field to .NET Core 3.1 if you use it.

using System;

namespace CSharpFeatures
{
    class Program
    {
        static void Main()
        {
            using (var disposableItem = new DisposableClass())
            {
                Console.WriteLine("Inside of the using statement");
            }
        }
    }

    class DisposableClass : IDisposable
    {
        public void Dispose()
        {
            // Release resources, close any connections, etc... 
            Console.WriteLine("I'm disposing!");
        }
    }
}

In C#, using statements define a new scope block. Any variables declared inside of a using statement are local to that block. At the end of that new scope the dispose method for that object is called.

Another way to ensure the correct use of disposable classes is to use a try-finally block. The finally keyword guarantees that the dispose method will be called.

using System;

namespace CSharpFeatures
{
    class Program
    {
        static void Main()
        {
            var disposableItem = new DisposableClass();
            try
            {
                Console.WriteLine("Inside of the try block");
            }
            finally
            {
                disposableItem.Dispose();
            }
        }
    }

    class DisposableClass : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("I'm disposing!");
        }
    }
}

This works, but the using statement is easier to read. There are fewer lines of code and less indentation.

The using declaration

One of the main downsides of using statements is that you have to declare a new scope block to implement them, but the last thing you want when trying to write clear code is an extraneous scope in a method. In C# 8, however, you no longer have to constrain your using statements with curly brackets. Instead, they can roam freely within the scope of the block in which they are declared.
🐃

Upon the end of the enclosing scope, any variables declared with the using keyword are disposed of.
↣🐃

Here’s an example of the new syntax:

using System;

namespace CSharpFeatures
{
    class Program
    {
        static void Main()
        {
            using var disposableItem = new DisposableClass();
            Console.WriteLine("Inside of the using statement");
        }
    }

    class DisposableClass : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("I'm disposing!");
        }
    }
}

Gotchas

While big-time programmers are fans of the terseness of the using declaration, there are some minor downsides. The first downside is that the standard using statement makes it obvious that the scope of your disposable class has a beginning and end. C# 8 using declarations blend into your code more and are less obvious.

Additionally, because it looks like a standard variable declaration, you could easily copy and paste the declaration when you refactor a method into smaller methods, which can produce some unexpected results. While you’d never do this normally, you might occasionally be coding before having had enough caffeine to fully wake up.

Here’s an example of what not to do. Imagine refactoring the instantiation of the disposable class into a method. The using declaration will get copied and dispose of the class before it gets used. 😯

using System;

namespace CSharpFeatures
{
    class Program
    {
        // Don't do this
        static void Main()
        {
            // This one comes in already disposed
            var disposableItem1 = CreateDisposableClass();

            // This instance gets disposed twice
            using var disposableItem2 = CreateDisposableClass();
            Console.WriteLine("Inside of the using statement");
        }

        private static DisposableClass CreateDisposableClass()
        {
            using var disposableItem = new DisposableClass();
            return disposableItem;
        }
    }

    class DisposableClass : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("I'm disposing!");
        }
    }
}

To fix this, make sure your using declaration is placed in the method that uses the class. You can still refactor your declaration code, but don’t add the using declaration until you’re making use of the instance.

using System;

namespace CSharpFeatures
{
        class Program
        {

            static void Main()
            {
                using var disposableItem = CreateDisposableClass();
                Console.WriteLine("Inside of the using statement");
            }
            
            private static DisposableClass CreateDisposableClass(){                    
                    var disposableItem = new DisposableClass();
                    return disposableItem;
            }
    }
    
        class DisposableClass : IDisposable
        {
            public void Dispose()
                    {
                Console.WriteLine("I'm disposing!");
            }
        }
}

Summary

The using statement makes code noticeably cleaner while still safely disposing of the object. While this isn’t going to revolutionize your life, it’s small upgrades like this that make C# a great language for day-to-day development. The next time you need to safely use some disposable objects, skip the curly braces and try out a using declaration.

Additional resources

Refer to the following sources for additional information, more code samples, and alternate perspectives:

C# Reference: using statement – The canonical documentation on docs.microsoft.com provides interesting examples and some discussion of best practices.

C# Reference: try-finally – Learn more about using a finally block for cleanup.

TwilioQuest – Still getting your C# sea legs? (See what I did there?) Learn new programming skills and have fun doing it with this free adventure game inspired by the 16-bit golden age. 🏄🏻‍♀️

Dustin Ewers is a software developer hailing from Southern Wisconsin. He helps people build better software. Dustin has been building software for over 10 years, specializing in Microsoft technologies. He is an active member of the technical community, speaking at user groups and conferences in and around Wisconsin. He writes about technology at https://www.dustinewers.com. Follow him on Twitter at @DustinJEwers.

No bison were harmed during the production of this post.