IDisposable и оператор using
Часть раздела Объектно-ориентированное программирование путешествия по C# на Coddy. Урок 45 из 70.
Некоторые объекты удерживают ресурсы, которые сборщик мусора не может автоматически очистить, — дескрипторы файлов, подключения к базам данных, сетевые сокеты. Интерфейс IDisposable предоставляет стандартный способ освободить эти ресурсы, когда они вам больше не нужны.
Класс implements 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())
{
// Работа с handler
} // Dispose() вызывается автоматически здесьСовременный C# предлагает более чистый синтаксис с объявлением using, которое освобождает объект, когда он выходит из области видимости:
void ProcessFile()
{
using FileHandler handler = new FileHandler();
// Работа с handler
} // Dispose() вызывается при выходе из методаИнструкция using работает с любым типом, который реализует IDisposable. Встроенные классы, такие как StreamReader, SqlConnection и HttpClient, реализуют этот интерфейс, что делает правильное управление ресурсами простым и надёжным.
Задание
ЛегкоДавайте создадим симулятор подключения к базе данных, демонстрирующий правильное управление ресурсами с использованием интерфейса IDisposable и оператора using. Вы создадите class, отслеживающий момент открытия и закрытия подключений и гарантирующий, что ресурсы всегда освобождаются должным образом.
Вы организуете код в двух файлах:
DatabaseConnection.cs: создайте classDatabaseConnectionв namespaceDataAccess, который implementsIDisposable. Ваше подключение должно:- иметь property
ConnectionName(строка, доступная только для чтения), устанавливаемую через constructor - отслеживать, было ли подключение освобождено, с помощью private boolean field
- выводить
Connection opened: {ConnectionName}при создании объекта (в constructor) - реализовывать method
Dispose(), выводящийConnection closed: {ConnectionName}— но only если объект ещё не был освобождён (чтобы prevent двойное освобождение) - иметь method
Query(string sql), возвращающийExecuting on {ConnectionName}: {sql}
- иметь property
Program.cs: в основном файле продемонстрируйте правильное управление ресурсами, используя операторusingвместе с подключением к базе данных. Создайте подключение, выполните запрос и позвольте блокуusingавтоматически выполнить очистку.
Вы получите два входных значения:
- имя подключения (например,
MainDB) - SQL-запрос для выполнения (например,
SELECT * FROM Users)
Используйте оператор using для создания подключения. Inside блока вызовите method Query и выведите его результат. Когда блок using ends, Dispose() будет вызван automatically.
Например, если входными значениями являются MainDB и SELECT * FROM Users, вывод должен быть таким:
Connection opened: MainDB
Executing on MainDB: SELECT * FROM Users
Connection closed: MainDBОбратите внимание, как подключение автоматически закрывается, когда блок using ends — вам never приходится помнить о необходимости вручную вызывать 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
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыПространства имен и директивыВведение в классы и объектыКлючевое слово 'this'Методы и параметрыПоля и свойстваКонструкторыИнициализаторы объектовИтоги — Простой калькулятор4Наследование
Основы синтаксиса наследования (:)Ключевое слово 'base'Ключевые слова Virtual и OverrideЗапечатанные классыБазовый класс 'object'Итоги — Иерархия сотрудников7Продвинутые возможности
Перегрузка операторовИндексаторы (this[])Переопределение ToString()Методы расширенияПовторение — Пользовательский список10Паттерны проектирования. Часть 1
Введение в паттерны проектированияПотокобезопасный SingletonПаттерн FactoryПаттерн Observer (События)Паттерн Strategy13Финальные испытания
Платформа для онлайн-обученияКомпонент игрового персонажаСервис аренды транспорта2Свойства и статические члены
Автоматически реализуемые свойстваСвойства только для чтения и записиСтатические поля и методыСтатические классыЧлены в виде выражений5Полиморфизм и интерфейсы
Полиморфизм: компиляция vs выполнениеИнтерфейс vs абстрактный классМножественные интерфейсыЯвные интерфейсыUpcasting и DowncastingИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция вместо наследованияGenerics (классы и методы)Делегаты и событияАтрибуты и рефлексияIDisposable и оператор usingОсновы Dependency Injection11Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн Компоновщик3Архитектура классов
Экземплярные и статические данныеКлючевые слова 'readonly' и 'const'Опорные поляПовторение — Менеджер банковских счетов6Инкапсуляция
Модификаторы доступаСвойства для инкапсуляцииРеализация скрытия данныхПаттерны неизменяемостиИтоги — Записи студентов9Переменное количество аргументов
Ключевое слово 'params'Необязательные параметрыИменованные аргументыПерегрузка методовПотренируйтесь самостоятельно: Онлайн-компилятор C#