Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Финализаторы и интерфейс IDisposable






Обсудим автоматическую сборку мусора с точки зрения программиста, разрабатывающего некий класс. С одной стороны, такой подход имеет свои преимущества. В частности, практически исключаются случайные утечки памяти, которые могут вызвать «забытые» объекты. Однако объект может в процессе создания или работы резервировать неуправляемые системные ресурсы, которые нужно освободить после того, как объект перестаёт использоваться. Примерами таких ресурсов являются открытый операционной системой файл или сетевое подключение. Платформа.NET предлагает подход, обеспечивающий автоматическое освобождение ресурсов при уничтожении объекта. Тип System.Object содержит виртуальный метод Finalize(). Класс (но не структура!) может переопределить этот метод для освобождения неуправляемых ресурсов. Объект такого класса обрабатывается особо при размещении в куче и при сборке мусора. При размещении ссылка на объект запоминается в специальной внутренней структуре CLR. При сборке мусора эта ссылка перемещается в очередь завершения (freachable queue). Затем в отдельном программном потоке у объектов из очереди завершения происходит вызов метода Finalize(), после этого ссылка на объект удаляется из очереди завершения.

Язык C# не позволяет явно переопределить в пользовательском классе метод Finalize(). Вместо этого в классе описывается специальный финализатор. Имя финализатора имеет вид ~имя-класса(), он не имеет параметров и модификаторов доступа (считается, что у него модификатор доступа protected). При наследовании в финализатор класса-наследника автоматически подставляется вызов финализатора класса-предка.

Приведём пример класса с финализатором:

public class ClassWithFinalizer

{

public void DoSomething()

{

Console.WriteLine(" I am working...");

}

 

~ClassWithFinalizer()

{

// здесь должен быть код освобождения неуправляемых ресурсов

Console.WriteLine(" Bye! ");

}

}

Вызов метода Finalize() является недетерминированным. Для освобождения управляемых ресурсов (т. е. ресурсов платформы.NET) программист может описать в классе некий метод, который следует вызывать вручную, когда ресурс больше не нужен. Для унификации данного решения предлагается интерфейс IDisposable с единственным методом Dispose(). Если класс или структура реализуют этот интерфейс, Dispose() содержит код освобождения управляемых ресурсов.

public class ClassWithDispose: IDisposable

{

public void DoSomething()

{

Console.WriteLine(" I am working...");

}

 

public void Dispose()

{

// здесь должен быть код освобождения управляемых ресурсов

Console.WriteLine(" Bye! ");

}

}

Язык C# имеет специальный оператор using, который гарантирует вызов метода Dispose() для заданных переменных в конце блока кода. Синтаксис оператора using следующий:

using (получение-ресурса) вложенный-оператор

Здесь получение-ресурса означает один из вариантов.

1. Объявление и инициализацию локальной переменой (или списка переменных). Тип переменной должен реализовывать IDisposable. Такая переменная в блоке using доступна только для чтения.

2. Выражение, значение которого имеет тип, реализующий IDisposable.

Приведём пример использования оператора using:

using (ClassWithDispose x = new ClassWithDispose())

{

x.DoSomething();

// компилятор C# поместит сюда вызов x.Dispose()

}






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.