Menu
Coddy logo textTech

IDisposable и оператор using

Часть раздела Объектно-ориентированное программирование путешествия по C# на Coddy — урок 45 из 70.

Некоторые объекты удерживают ресурсы, которые сборщик мусора не может очистить автоматически — дескрипторы файлов, подключения к базам данных, сетевые сокеты. Интерфейс IDisposable предоставляет стандартный способ освобождения этих ресурсов, когда вы закончите с ними работать.

Класс реализует IDisposable путем предоставления метода Dispose():

public class FileHandler : IDisposable
{
    private bool disposed = false;
    
    public void Dispose()
    {
        if (!disposed)
        {
            Console.WriteLine("Releasing resources...");
            disposed = true;
        }
    }
}

Вы могли бы вызвать Dispose() вручную, но что если исключение возникнет до того, как вы дойдете до этой строки? Оператор using гарантирует выполнение очистки, даже если что-то пойдет не так:

using (FileHandler handler = new FileHandler())
{
    // Работа с обработчиком
}  // Dispose() вызывается здесь автоматически

Современный C# предлагает более чистый синтаксис с объявлением using, которое освобождает объект, когда он выходит из области видимости:

void ProcessFile()
{
    using FileHandler handler = new FileHandler();
    // Работа с handler
}  // Dispose() вызывается при выходе из метода

Оператор using работает с любым типом, который реализует IDisposable. Встроенные классы, такие как StreamReader, SqlConnection и HttpClient, реализуют этот интерфейс, что делает правильное управление ресурсами простым и надежным.

challenge icon

Задание

Легко

Давайте создадим симулятор подключения к базе данных, который демонстрирует правильное управление ресурсами с использованием интерфейса IDisposable и оператора using. Вы создадите класс, который отслеживает открытие и закрытие соединений, гарантируя, что ресурсы всегда освобождаются должным образом.

Вы организуете свой код в двух файлах:

  • DatabaseConnection.cs: Создайте класс DatabaseConnection в пространстве имен DataAccess, который реализует интерфейс IDisposable. Ваше соединение должно:
    • Иметь свойство ConnectionName (строка, только для чтения), устанавливаемое через конструктор
    • Отслеживать, было ли соединение освобождено, используя закрытое логическое поле
    • Выводить Connection opened: {ConnectionName} при создании объекта (в конструкторе)
    • Реализовать метод Dispose() для вывода Connection closed: {ConnectionName} — но только если объект еще не был освобожден (предотвращение двойного освобождения)
    • Иметь метод Query(string sql), который возвращает Executing on {ConnectionName}: {sql}
  • Program.cs: В основном файле продемонстрируйте правильное управление ресурсами, используя оператор using с вашим подключением к базе данных. Создайте соединение, выполните запрос и позвольте блоку using автоматически обработать очистку.

Вы получите два входных значения:

  • Имя соединения (например, MainDB)
  • SQL-запрос для выполнения (например, SELECT * FROM Users)

Используйте оператор using для создания соединения. Внутри блока вызовите метод Query и выведите его результат. Когда блок using завершится, метод Dispose() будет вызван автоматически.

Например, если входные данные — MainDB и SELECT * FROM Users, вывод должен быть следующим:

Connection opened: MainDB
Executing on MainDB: SELECT * FROM Users
Connection closed: MainDB

Обратите внимание, как соединение автоматически закрывается при завершении блока using — вам никогда не придется вызывать Dispose() вручную. Этот паттерн гарантирует, что ресурсы всегда будут очищены, даже если внутри блока возникнет исключение!

Попробуйте сами

using System;
using DataAccess;

class Program
{
    public static void Main(string[] args)
    {
        string connectionName = Console.ReadLine();
        string sqlQuery = Console.ReadLine();
        
        // TODO: Используйте оператор 'using' для создания DatabaseConnection
        // Внутри блока using:
        // 1. Вызовите метод Query с sqlQuery
        // 2. Выведите результат метода Query
        // Метод Dispose будет вызван автоматически по завершении блока using
        
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование