C# Using (How it Works for Developers)

If you're just starting out with C# programming or even if you have some experience, you're in the right place. In this tutorial, we'll explore the using statement, its purpose, and how to use it effectively in your code. So, let's dive in!

What is the Using Statement?

The using statement in C# is a convenient way to work with resources that implement the IDisposable interface. IDisposable objects typically hold onto unmanaged resources, like file handles or network connections, that need to be released when you're done using them. This is where the using statement comes into play - it helps you to ensure that these resources are properly disposed of after use. For example, the using statement is very helpful in C#

How the Using Statement Works

When you use the using statement, C# will automatically call the Dispose method on the object when it's no longer needed. This means you don't have to manually call the Dispose method or worry about forgetting to do so. The using statement takes care of this for you!

Let's take a look at a simple example to see how the using statement works in action:


    using System.IO;

    class Program
    {
        static void Main()
        {
            using (StreamReader reader = new StreamReader("example.txt"))
            {
                string content = reader.ReadToEnd();
                Console.WriteLine(content);
            }
        }
    }

    using System.IO;

    class Program
    {
        static void Main()
        {
            using (StreamReader reader = new StreamReader("example.txt"))
            {
                string content = reader.ReadToEnd();
                Console.WriteLine(content);
            }
        }
    }
Imports System.IO

	Friend Class Program
		Shared Sub Main()
			Using reader As New StreamReader("example.txt")
				Dim content As String = reader.ReadToEnd()
				Console.WriteLine(content)
			End Using
		End Sub
	End Class
VB   C#

In this example, the StreamReader object named reader is wrapped in a using block. When the using block is exited, the Dispose method is automatically called on the reader, freeing up any resources it was holding onto.

Using Block vs. Using Declaration

Starting with C# 8.0, you can use the using declaration instead of the using block. The using declaration is a shorter and more concise way to define a disposable object, like so:


    using System.IO;

    class Program
    {
        static void Main()
        {
            using var reader = new StreamReader("example.txt");
            string content = reader.ReadToEnd();
            Console.WriteLine(content);
        }
    }

    using System.IO;

    class Program
    {
        static void Main()
        {
            using var reader = new StreamReader("example.txt");
            string content = reader.ReadToEnd();
            Console.WriteLine(content);
        }
    }
Imports System.IO

	Friend Class Program
		Shared Sub Main()
			Dim reader = New StreamReader("example.txt")
			Dim content As String = reader.ReadToEnd()
			Console.WriteLine(content)
		End Sub
	End Class
VB   C#

With the using declaration, you don't need the curly braces or indentation, making your code more readable. The Dispose method is still called automatically when the variable goes out of scope.

Try Block, Finally Block, and the Using Statement

You might be wondering how the using statement relates to the try and finally blocks in C#. Well, the using statement is actually a shorthand for a try-finally block!

Here's the same example as before, but written using a try-finally block instead of a using statement:


    using System.IO;

    class Program
    {
        static void Main()
        {
            StreamReader reader = null;
            try
            {
                reader = new StreamReader("example.txt");
                string content = reader.ReadToEnd();
                Console.WriteLine(content);
            }
            finally
            {
                if (reader != null)
                {
                    reader.Dispose();
                }
            }
        }
    }

    using System.IO;

    class Program
    {
        static void Main()
        {
            StreamReader reader = null;
            try
            {
                reader = new StreamReader("example.txt");
                string content = reader.ReadToEnd();
                Console.WriteLine(content);
            }
            finally
            {
                if (reader != null)
                {
                    reader.Dispose();
                }
            }
        }
    }
Imports System.IO

	Friend Class Program
		Shared Sub Main()
			Dim reader As StreamReader = Nothing
			Try
				reader = New StreamReader("example.txt")
				Dim content As String = reader.ReadToEnd()
				Console.WriteLine(content)
			Finally
				If reader IsNot Nothing Then
					reader.Dispose()
				End If
			End Try
		End Sub
	End Class
VB   C#

As you can see, the using statement makes the code cleaner and easier to read by removing the need for the try-finally block and the explicit call to the Dispose method.

Managing Multiple Resources

One of the great things about the using statement is that it can handle multiple resources at once. You can stack using statements one after another, or use a single using statement to handle multiple resources in a comma-separated list. Here's an example that demonstrates both approaches:


    using System.IO;

    class Program
    {
        static void Main()
        {
            using (StreamReader reader1 = new StreamReader("example1.txt"))
            using (StreamReader reader2 = new StreamReader("example2.txt"))
            {
                string content1 = reader1.ReadToEnd();
                string content2 = reader2.ReadToEnd();
                Console.WriteLine($"Content from example1.txt:\n{content1}\nContent from example2.txt:\n{content2}");
            }

            // Alternatively, you can use a single using statement with multiple resources:

            using (StreamReader reader1 = new StreamReader("example1.txt"), reader2 = new StreamReader("example2.txt"))
            {
                string content1 = reader1.ReadToEnd();
                string content2 = reader2.ReadToEnd();
                Console.WriteLine($"Content from example1.txt:\n{content1}\nContent from example2.txt:\n{content2}");
            }
        }
    }

    using System.IO;

    class Program
    {
        static void Main()
        {
            using (StreamReader reader1 = new StreamReader("example1.txt"))
            using (StreamReader reader2 = new StreamReader("example2.txt"))
            {
                string content1 = reader1.ReadToEnd();
                string content2 = reader2.ReadToEnd();
                Console.WriteLine($"Content from example1.txt:\n{content1}\nContent from example2.txt:\n{content2}");
            }

            // Alternatively, you can use a single using statement with multiple resources:

            using (StreamReader reader1 = new StreamReader("example1.txt"), reader2 = new StreamReader("example2.txt"))
            {
                string content1 = reader1.ReadToEnd();
                string content2 = reader2.ReadToEnd();
                Console.WriteLine($"Content from example1.txt:\n{content1}\nContent from example2.txt:\n{content2}");
            }
        }
    }
Imports Microsoft.VisualBasic
Imports System.IO

	Friend Class Program
		Shared Sub Main()
			Using reader1 As New StreamReader("example1.txt")
			Using reader2 As New StreamReader("example2.txt")
				Dim content1 As String = reader1.ReadToEnd()
				Dim content2 As String = reader2.ReadToEnd()
				Console.WriteLine($"Content from example1.txt:" & vbLf & "{content1}" & vbLf & "Content from example2.txt:" & vbLf & "{content2}")
			End Using
			End Using

			' Alternatively, you can use a single using statement with multiple resources:

			Using reader1 As New StreamReader("example1.txt"), reader2 As New StreamReader("example2.txt")
				Dim content1 As String = reader1.ReadToEnd()
				Dim content2 As String = reader2.ReadToEnd()
				Console.WriteLine($"Content from example1.txt:" & vbLf & "{content1}" & vbLf & "Content from example2.txt:" & vbLf & "{content2}")
			End Using
		End Sub
	End Class
VB   C#

Both of these approaches will ensure that the Dispose method is called on each StreamReader object when the using block is exited, releasing any resources they were holding onto.

Implementing IDisposable Interface

Sometimes, you might create your own custom classes that manage one or more resources. If your class is responsible for handling disposable objects or unmanaged resources, you should implement the IDisposable interface.

Here's an example of a custom class that implements the IDisposable interface:


    using System;
    using System.IO;

    public class CustomResource : IDisposable
    {
        private StreamReader _reader;

        public CustomResource(string filePath)
        {
            _reader = new StreamReader(filePath);
        }

        public void ReadContent()
        {
            string content = _reader.ReadToEnd();
            Console.WriteLine(content);
        }

        public void Dispose()
        {
            if (_reader != null)
            {
                _reader.Dispose();
                _reader = null;
            }
        }
    }

    using System;
    using System.IO;

    public class CustomResource : IDisposable
    {
        private StreamReader _reader;

        public CustomResource(string filePath)
        {
            _reader = new StreamReader(filePath);
        }

        public void ReadContent()
        {
            string content = _reader.ReadToEnd();
            Console.WriteLine(content);
        }

        public void Dispose()
        {
            if (_reader != null)
            {
                _reader.Dispose();
                _reader = null;
            }
        }
    }
Imports System
	Imports System.IO

	Public Class CustomResource
		Implements IDisposable

		Private _reader As StreamReader

		Public Sub New(ByVal filePath As String)
			_reader = New StreamReader(filePath)
		End Sub

		Public Sub ReadContent()
			Dim content As String = _reader.ReadToEnd()
			Console.WriteLine(content)
		End Sub

		Public Sub Dispose() Implements IDisposable.Dispose
			If _reader IsNot Nothing Then
				_reader.Dispose()
				_reader = Nothing
			End If
		End Sub
	End Class
VB   C#

In this example, the CustomResource class manages a StreamReader object, which is a disposable object. By implementing the IDisposable interface and implementing a Dispose method, we can use the using statement with instances of this class.

Here's how you would use the using statement with the CustomResource class:

class Program
{
    static void Main()
    {
        using (CustomResource resource = new CustomResource("example.txt"))
        {
            resource.ReadContent();
        }
    }
}
class Program
{
    static void Main()
    {
        using (CustomResource resource = new CustomResource("example.txt"))
        {
            resource.ReadContent();
        }
    }
}
Friend Class Program
	Shared Sub Main()
		Using resource As New CustomResource("example.txt")
			resource.ReadContent()
		End Using
	End Sub
End Class
VB   C#

When the using block terminates, the Dispose method will be called, disposing of the StreamReader object it manages.

Handling Exceptions with the Using Statement

Another benefit of the using statement is that it helps handle exceptions more gracefully. If an exception occurs within the using block, the Dispose method will still be called on the resource, ensuring proper cleanup.

For example, consider the following code:

using System;
using System.IO;

class Program
{
    static void Main()
    {
        try
        {
            using (StreamReader reader = new StreamReader("nonexistentfile.txt"))
            {
                string content = reader.ReadToEnd();
                Console.WriteLine(content);
            }
        }
        catch (FileNotFoundException ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}
using System;
using System.IO;

class Program
{
    static void Main()
    {
        try
        {
            using (StreamReader reader = new StreamReader("nonexistentfile.txt"))
            {
                string content = reader.ReadToEnd();
                Console.WriteLine(content);
            }
        }
        catch (FileNotFoundException ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}
Imports System
Imports System.IO

Friend Class Program
	Shared Sub Main()
		Try
			Using reader As New StreamReader("nonexistentfile.txt")
				Dim content As String = reader.ReadToEnd()
				Console.WriteLine(content)
			End Using
		Catch ex As FileNotFoundException
			Console.WriteLine($"Error: {ex.Message}")
		End Try
	End Sub
End Class
VB   C#

In this case, if the code throws a FileNotFoundException, the exception is caught and handled by the catch block. Even though the exception occurred within the using block, the Dispose method is still called on the StreamReader object, ensuring that no resources are leaked.

Working with IronPDF and the Using Statement

IronPDF is a popular library for creating, editing, and extracting PDF files in C# and .NET applications. Like other libraries that work with resources, IronPDF can also benefit from the using statement to ensure proper resource management.

Let's explore how to use the using statement with IronPDF to create a PDF document from an HTML string, demonstrating the power of the using statement in a real-life scenario.

First, make sure you've installed the IronPDF NuGet package in your project:

```shell
:ProductInstall

Now, let's extract data all data from the PDF file:

```cs
using IronPdf;

class Program
{
    static void Main()
    {
        using (PdfDocument pdfDocument = PdfDocument.FromFile("PDFData.pdf"))
        {
            string extractedText = pdfDocument.ExtractAllText();
            Console.WriteLine(extractedText);
        }
    }
}

In this code, we open a PDF file named "PDFData.pdf" using the PdfDocument.FromFile method. This method returns a PdfDocument instance, which we wrap in a using statement.

Inside the using block, we call ExtractAllText on the PdfDocument instance to extract all text from the PDF. When the using block is exited, the Dispose method is automatically called on the PdfDocument, releasing any resources it was holding onto.

By using the using statement with PdfDocument, we ensure that the PDF file is properly closed after we're done extracting text from it, even if an exception occurs during the process. This is a good example of how the using statement can help manage resources effectively in C#.

C# Using (How It Works For Developers) Figure 1

Wrapping Up

In this tutorial, we've delved deep into the C# using statement, exploring its purpose, functionality, and real-world application. We've seen how it ensures the efficient handling of disposable objects, managing one or more resources seamlessly. The using statement not only aids in maintaining cleaner code but also enhances the readability of your C#

We also introduced IronPDF, a robust library for PDF manipulation in C#. Employing the using statement in conjunction with IronPDF demonstrates this code feature's practical application, reinforcing the concept and its importance.

IronPDF offers a free trial, giving you ample opportunity to test its capabilities and see how it can benefit your projects. Licensing starts from $749.