Читаем Язык программирования С# 2005 и платформа .NET 2.0. полностью

 // Пользователь объекта вызывает этот метод для того, чтобы

 // как можно быстрее освободить ресурсы.

 public void Dispose() {

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

  // Вызов Dispose() для содержащихся объектов,

  // предусматривающих освобождение ресурсов.

  // Если пользователь вызвал Dispose(), то финализация не нужна.

  GC.SuppressFinalize(this);

 }

}

Обратите внимание на то, что в метод Dispose() здесь добавлен вызов GC.SuppressFinalize(), информирующий среду CLR о том, что теперь при сборке мусора не требуется вызывать деструктор, поскольку неуправляемые ресурсы уже освобождены с помощью программной логики Dispose().

<p>Формализованный шаблон освобождения ресурсов</p>

Текущая реализация MyResourceWrapper работает вполне приемлемо, но некоторые недостатки она все же имеет. Во-первых, каждому из методов Finalize() и Dispose() приходится очищать одни и те же неуправляемые ресурсы. Это, конечно, ведет к дублированию программного кода, что усложняет задачу его поддержки. Лучше всего определить приватную вспомогательную функцию, которая вызывалась бы каждым из двух этих методов.

Далее, следует убедиться в том, что метод Finalize() не пытается освободить управляемые объекты, которые должны обрабатываться методом Dispose(). Наконец, желательно гарантировать, что пользователь объекта сможет многократно вызывать метод Disposed без появления сообщений об ошибке. В настоящий момент наш метод Dispose() таких гарантий не дает.

Для решения указанных проблемы Microsoft определила формализованный шаблон для освобождения ресурсов, устанавливающий баланс между устойчивостью к ошибкам, производительностью и простотой поддержки. Вот окончательная (и аннотированная) версия MyResourceWrapper, для которой используется этот "официальный" шаблон.

public class MyResourceWrapper: IDisposable {

 // Используется для того, чтобы выяснить,

 // вызывался ли метод Dispose().

 private bool disposed = false;

 public void Dispose() {

  // Вызов нашего вспомогательного метода.

  // Значение "true" указывает на то, что

  // очистку инициировал пользователь объекта.

  CleanUp(true);

  // Запрет финализации.

  GC.SuppressFinalize(this);

 }

 private void CleanUp(bool disposing) {

  // Убедимся, что ресурсы еще не освобождены.

  if (!this.disposed) {

   // Если disposing равно true, освободить

   // все управляемые ресурсы.

   if (disposing) {

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

   }

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

  }

  disposed = true;

 }

 ~MyResourceWrapper() {

  // Вызов нашего вспомогательного метода.

  // Значение "false" указывает на то, что

  // очистку инициировал сборщик мусора.

  CleanDp(false);

 }

}

Обратите внимание на то, что теперь MyResourceWrapper определяет приватный вспомогательный метод, с именем Cleanup(). Если для его аргумента указано true (истина), это значит, что сборку мусора инициировал пользователь объекта. И тогда мы должны освободить и управляемые, и неуправляемые ресурсы. Но если "уборка" инициирована сборщиком мусора, то при вызове CleanUp() следует указать false (ложь), чтобы внутренние объекты не освобождались (поскольку мы не можем гарантировать, что они все еще находятся в памяти). Наконец, перед выходом из CleanUp() член-переменная disposed логического типа устанавливается равной true, чтобы Dispose() можно было вызывать многократно без появления сообщений об ошибках.

Исходный код. Проект FinalizableDisposableClass размещен в подкаталоге, соответствующем главе 5.

На этом наше обсуждение того, как среда CLR управляет объектами с помощью сборки мусора, завершается. Остались нерассмотренными еще ряд вопросов, связанных с процессом сборки мусора (это, например, слабые ссылки и восстановление объектов), но вы теперь имеете достаточно знаний для того, чтобы продолжить исследование данной темы самостоятельно в удобное для вас время.

<p>Резюме</p>
Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT