Чтение онлайн

на главную - закладки

Жанры

ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Троелсен Эндрю

Шрифт:

При размещений объекта в управляемой динамической памяти среда выполнения автоматически определяет, поддерживает ли этот объект пользовательский метод Finalize. Если указанный метод поддерживается, то объект обозначается, как требующий финализации, а указатель на этот объект сохраняется во внутренней очереди, которую называют очередью финализации. Очередь финализации представляет собой таблицу, поддерживаемую сборщиком мусора и содержащую все объекты, для которых перед удалением из динамической памяти требуется финализация.

Когда с точки зрения сборщика мусора приходит время удалить объект из памяти,

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

Таким образом, хотя финализация объекта и гарантирует, что объект сможет освободить неуправляемые ресурсы, по своей природе эта процедура оказывается недетерминированной и, в связи с происходящими "за кулисами" дополнительными процессами, достаточно медленной.

Создание объектов, предусматривающих освобождение ресурсов

Поскольку многие неуправляемые ресурсы являются столь "драгоценными", что их нужно освободить как можно быстрее, предлагается рассмотреть еще один подход, используемый для "уборки" ресурсов объекта. В качестве альтернативы переопределению Finalize класс может реализовать интерфейс IDisposable, который определяет единственный метод, имеющий имя Dispose.

public interface IDisposable {

 void Dispose;

}

Если вы не имеете опыта программирования интерфейсов, то в главе 7 вы найдете все необходимые подробности. В сущности, интерфейс представляет собой набор абстрактных членов, которые могут поддерживаться классом или структурой. Если вы реализуете поддержку интерфейса IDisposable, то предполагается, что после завершения работы с объектом пользователь объекта должен вручную вызвать Dispose до того, как объектная ссылка "уйдет" из области видимости. При таком подходе ваши объекты смогут выполнить всю необходимую "уборку" неуправляемых ресурсов без размещения в очереди финализации и без ожидания сборщика мусора, запускающего программную логику финализации класса.

Замечание. Интерфейс IDisposable может поддерживаться и типами структуры, и типами класса (в отличие от переопределения Finalize, которое годится только для типов класса).

Ниже показан обновленный класс MyResourceWrapper, который теперь реализует IDisposable вместо переопределения System.Object.Finalize .

// Реализация IDisposable.

public class MyResourceWrapper: IDisposable {

 // Пользователь объекта должен вызвать этот метод

 // перед завершением работы с объектом.

 public void Dispose {

// Освобождение неуправляемых ресурсов.

// Освобождение других содержащихся объектов.

 }

}

Обратите

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

public class Program {

 static void Main {

MyResourceWrapper rw = new MyResourceWrapper;

rw.Dispose;

Console.ReadLine;

 }

}

Конечно, перед попыткой вызвать Dispose для объекта вы должны проверить, что соответствующий тип поддерживает интерфейс IDisposable. Обычно информацию об этом вы будете получать из документации .NET Framework 2.0 SDK, но это можно выяснить и программными средствами, используя ключевые слова is или as, применение которых обсуждалось в главе 4.

public class Program {

 static void Main {

MyResourceWrapper rw = new MyResourceWrapper;

if (rw is IDisposable) rw.Dispose;

Console.ReadLine;

 }

}

Этот пример заставляет вспомнить еще одно правило работы с типами, предполагающими сборку мусора.

• Правило. Обязательно вызывайте Dispose для любого возданного вами объекта, поддерживающего IDisposable. Если разработчик класса решил реализовать поддержку метода Dispose, то типу, скорее всего, есть что "убирать".

Снова о ключевом слове using в C#

При обработке управляемых объектов, реализующих интерфейс IDisposable, вполне типичным будет использование методов структурированной обработки исключений (см. главу 6), чтобы гарантировать вызов метода Dispose даже при возникновении исключительных ситуаций в среде выполнения.

static void Main(string[] args) {

 MyResourceWrapper rw = new MyResourceWrapper;

 try {

// Использование членов rw.

 } finally {

// Dispose вызывается всегда, есть ошибки или нет.

rw.Dispose;

 }

}

Этот пример применения технологии "Безопасного программирования" прекрасен, но реальность такова, что лишь немногие разработчики готовы мириться с перспективой помещения каждого типа, предполагающего освобождение ресурсов, в рамки блока try/catch/finally только для того, чтобы гарантировать вызов метода Dispose. Поэтому для достижения того же результата в C# предусмотрен намного более удобный синтаксис, реализуемый с помощью ключевого слова using.

Поделиться:
Популярные книги

Дракон с подарком

Суббота Светлана
3. Королевская академия Драко
Любовные романы:
любовно-фантастические романы
6.62
рейтинг книги
Дракон с подарком

Бывшие. Война в академии магии

Берг Александра
2. Измены
Любовные романы:
любовно-фантастические романы
7.00
рейтинг книги
Бывшие. Война в академии магии

Мастер клинков. Начало пути

Распопов Дмитрий Викторович
1. Мастер клинков
Фантастика:
фэнтези
9.16
рейтинг книги
Мастер клинков. Начало пути

Имя нам Легион. Том 8

Дорничев Дмитрий
8. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 8

Измена. Право на счастье

Вирго Софи
1. Чем закончится измена
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Право на счастье

Начальник милиции 2

Дамиров Рафаэль
2. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции 2

Камень. Книга 4

Минин Станислав
4. Камень
Фантастика:
боевая фантастика
7.77
рейтинг книги
Камень. Книга 4

Измена. Мой заклятый дракон

Марлин Юлия
Любовные романы:
любовно-фантастические романы
7.50
рейтинг книги
Измена. Мой заклятый дракон

Предатель. Цена ошибки

Кучер Ая
Измена
Любовные романы:
современные любовные романы
5.75
рейтинг книги
Предатель. Цена ошибки

Звездная Кровь. Изгой

Елисеев Алексей Станиславович
1. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Звездная Кровь. Изгой

Рождение победителя

Каменистый Артем
3. Девятый
Фантастика:
фэнтези
альтернативная история
9.07
рейтинг книги
Рождение победителя

Барону наплевать на правила

Ренгач Евгений
7. Закон сильного
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Барону наплевать на правила

Камень. Книга шестая

Минин Станислав
6. Камень
Фантастика:
боевая фантастика
7.64
рейтинг книги
Камень. Книга шестая

Чужая дочь

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Чужая дочь