Skip to Content
Course content

171: The using Statement and using Declarations

Click on the "Edit" button in the top corner of the screen to edit your slide content.

A few years ago, I was reviewing a PR for a junior developer who had written a small utility to parse several large CSV files. The code looked clean, but as soon as we ran it against a folder with a few hundred files, the application crashed with a IOException: "The process cannot access the file because it is being used by another process." He was baffled because he wasn't opening the same file twice. The culprit? He was opening StreamReader instances inside a loop but never closing them. He assumed the Garbage Collector would just clean them up when he was done, but unmanaged resources like file handles don't work that way—they stay locked until the GC decides to run a collection, which might be way too late.

Managing Resources with the using Statement

In C#, any class that implements the IDisposable interface is telling you: "I am holding onto something that the .NET runtime can't manage automatically." This could be a file handle, a database connection, or a network socket. If you just let these objects go out of scope without calling Dispose(), you're essentially gambling with your system's resources.

The using statement is the gold standard for handling this. It creates a scope where the resource is guaranteed to be disposed of the moment the code exits that block, regardless of whether it exited normally or threw an exception. Under the hood, the compiler actually transforms this into a try-finally block, ensuring Dispose() is called in the finally section.

using (StreamWriter writer = new StreamWriter("log.txt"))
{
    writer.WriteLine("Log entry: Application started.");
    writer.WriteLine("Processing data...");
    // If an exception happens here, the file is still closed properly.
} 
// writer is disposed here automatically.

I generally recommend this block-based approach when you want the resource released as quickly as possible. If you're doing a lot of heavy lifting after the file operation in the same method, don't keep the file open longer than you need to.

Streamlining with using Declarations

If you find the nested curly braces of the traditional using statement make your code look like a pyramid of indentation, C# 8.0 introduced using declarations. This is a much leaner syntax that removes the need for the explicit block. Instead, the resource is disposed of when the variable goes out of scope—typically at the end of the method.

public void SaveUserPreferences(UserPrefs prefs)
{
    using var stream = new FileStream("prefs.dat", FileMode.Create);
    using var writer = new StreamWriter(stream);
    
    writer.WriteLine(prefs.Theme);
    writer.WriteLine(prefs.FontSize);
    
    // No curly braces needed. 
    // writer and stream are disposed when the method returns.
}

It's a cleaner look, and in many cases, it's exactly what you want. However, a word of caution: because the disposal happens at the end of the method, you lose fine-grained control. If you have a long-running method that does a quick file write at the beginning and then spends ten seconds calling a slow API, that file remains locked for those ten seconds. In those specific scenarios, stick to the block-based using statement to free the resource immediately.




📋 Practical Task

Exercise: Building a Robust Log Append Utility

You need to create a method called AppendToSystemLog that takes a string message and appends it to a file named system.log. To make this exercise effective, you must ensure the file is handled safely to prevent locking issues.

Requirements:

  • Implement the AppendToSystemLog method.
  • Use a StreamWriter to append the text to the file.
  • Apply a using declaration or statement to ensure the StreamWriter is disposed of immediately after the write operation is complete.
  • Include a timestamp at the beginning of each log entry (e.g., [2023-10-27 10:00:00] Message here).
  • Wrap the logic in a try-catch block to handle potential IOException errors, printing a user-friendly message to the console if the file is unavailable.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.