С какими объектами в C# можно использовать оператор `using`?

«С какими объектами в C# можно использовать оператор `using`?» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Оператор using в C# предназначен для автоматического вызова метода Dispose() у объекта, реализующего интерфейс IDisposable. Это гарантирует своевременное освобождение неуправляемых ресурсов (файловые дескрипторы, сокеты, соединения с БД), даже если в блоке кода произойдет исключение.

Основные типы объектов, которые используются с using:

  1. Работа с файловой системой: FileStream, StreamReader, StreamWriter.

    using (var streamReader = new StreamReader("data.txt"))
    {
        string content = await streamReader.ReadToEndAsync();
    } // streamReader.Dispose() вызывается автоматически
  2. Сетевые операции: HttpClient (хотя для него есть особенности), TcpClient.

    using (var httpClient = new HttpClient())
    {
        var response = await httpClient.GetAsync("https://api.example.com");
    }
  3. Работа с базами данных: SqlConnection, SqlCommand, DbContext (в Entity Framework).

    using (var connection = new SqlConnection(connectionString))
    {
        await connection.OpenAsync();
        using (var command = new SqlCommand("SELECT * FROM Users", connection))
        {
            // ...
        }
    } // Сначала закроется command, затем connection
  4. Графика (System.Drawing): Bitmap, Graphics, Pen.

Современный синтаксис (начиная с C# 8.0): Можно использовать using без фигурных скобок для объявления. Ресурс будет освобожден при выходе из текущей области видимости (метода).

public async Task ProcessDataAsync()
{
    using var file = File.OpenRead("input.txt");
    using var dbConnection = new SqlConnection(connectionString);
    // Работа с file и dbConnection...
} // Оба ресурса будут автоматически освобождены здесь

Важное замечание: using предназначен исключительно для типов, реализующих IDisposable. Не путать с директивой using для импорта пространств имен или using static для импорта статических членов класса.