Когда я должен использовать IDisposable, когда-нибудь неправильно его использовать? Как насчет удаления цепочки? - PullRequest
9 голосов
/ 01 августа 2010

Я действительно ищу лучшую мудрость для практики.Так что вот вопросы, я добавлю больше, если люди оставят комментарии.Не стесняйтесь ответить на некоторые или все эти вопросы.

Когда СЛЕДУЕТ использовать IDisposable?Только когда у меня есть неуправляемые ресурсы?

Какие существуют варианты схемы утилизации и почему они различаются?

Что такое общие неуправляемые ресурсыЯ должен знать?

Это когда-либо неправильно или вводить в заблуждение реализацию IDisposable?

Должны ли вызовы Dispose когда-либо объединяться илимы полагаемся на использование операторов? Например:

public Dispose(bool disposing)
{
  ...
  this.SomeDependency.Dispose;
}

Ответы [ 2 ]

6 голосов
/ 01 августа 2010

Ничего себе.Здесь много вопросов!

Когда я ДОЛЖЕН использовать IDisposable?Только когда у меня есть неуправляемые ресурсы?

IDisposable обычно обычно используется для очистки ресурсов, но это не обязательно все, для чего это хорошо.Это общая схема уведомления объекта потребления о том, что вы закончили с ним.Одним из примеров является таймер:

using(var timer = new MyTimer())
{
    //do some stuff
}

В этом случае вызов Dispose не обязательно освобождает какие-либо ресурсы, это просто удобный и последовательный (два ключа для шаблона!) Способ сообщить таймеру«Хорошо, я с тобой закончил», и таймер может остановить отсчет времени и, возможно, записать время где-нибудь.

Еще одно хорошее эмпирическое правило - если по какой-то причине вам нужен финализаторобычно должен также предоставить IDisposable доступ к той же самой подпрограмме, чтобы потребительский класс мог предпочесть завершить класс раньше, а не ждать в GC.

Какие существуют варианты шаблона dispose и почемуони различаются?

Существует только один реальный "конкретный" тип реализации IDisposable, о котором я знаю - шаблон Finalize / Dispose:

public class MyClass : IDisposable
{
   void IDisposable.Dispose() 
   {
     Dispose(true);
     GC.SuppressFinalize(this); 
   }

   protected virtual void Dispose(bool disposing) 
   {
      if (disposing) 
      {
         // Free other state (managed objects).
      }
      // Free your own state (unmanaged objects).
      // Set large fields to null.
   }

   ~MyClass()
   {
      Dispose(false);
   }
}

Что такое общие неуправляемые ресурсы, о которых мне следует знать?

Все, что реализует IDisposable, особенно в библиотеках .NET, должно иметь дескрипторы неуправляемых ресурсов и шо.должен быть расположен.Обычно через них вы получаете доступ только к неуправляемым ресурсам.Если нет, то вы будете знать - обычно сборка драйвера или что-то в этом роде.

Это когда-либо неправильно или вводит в заблуждение внедрение IDisposable?

Может быть бессмысленно злоупотреблять им, но не наносит непосредственного вреда.

Если вызовы Dispose когда-либо объединяются в цепочку

Класс должен располагать только теми IDisposable, которые он создает внутри.Если у него есть одноразовые зависимости, которые были введены или находятся за пределами класса, вы никогда не должны избавляться от них.

4 голосов
/ 01 августа 2010

В отношении IDisposable я написал две основные вещи, и я рекомендую вам прочитать хотя бы первую: Как реализовать IDisposable и Finalizer - 3 простых правила (у меня также есть другие сообщения в блоге на эту тему ) и IDisposable - что ваша мать никогда не говорила вам о выделении ресурсов .

Когда я ДОЛЖЕН использовать IDisposable? Только когда у меня есть неуправляемые ресурсы?

IDisposable следует использовать для одной из трех целей: освобождение неуправляемого ресурса, освобождение управляемых ресурсов и RAII. Я предпочитаю использовать разные шаблоны для этих разных нужд.

Обратите внимание, что все мои ответы (и ссылки) обсуждают IDisposable в контексте освобождения ресурсов. Они не обращаются к RAII.

Какие существуют варианты схемы утилизации и почему они различаются?

Шаблон Microsoft является наиболее известным. Он обрабатывает освобождение неуправляемых и управляемых ресурсов и позволяет наследовать. Я предпочитаю более простой шаблон, описанный в моем блоге ( 3 простых правила ), который является шаблоном, который Microsoft использует на самом деле , которому следуют после .NET 2.0.

Что такое общие неуправляемые ресурсы, о которых мне следует знать?

Я предпочитаю иметь один класс IDisposable для каждого типа неуправляемых ресурсов (сродни SafeFileHandle от Microsoft). Таким образом, каждый раз, когда вы добавляете неуправляемый ресурс в свою программу / библиотеку, вам нужно обрабатывать его только один раз.

Тогда возникает вопрос: «Какие классы мне следует располагать?», На что есть простой ответ: «Все классы, которые реализуют IDisposable

Является ли когда-либо неправильным или вводящим в заблуждение внедрение IDisposable?

Нет. Пустая реализация IDisposable всегда является опцией. Вы должны рассмотреть возможность добавления IDisposable к интерфейсам или базовым классам, если вы думаете, что реализация может их использовать. Это проблема дизайна, о которой я подробнее расскажу в моей статье «Что ваша мать никогда не говорила вам» .

Стоит ли когда-либо связывать вызовы Dispose или мы должны полагаться на использование операторов?

Обычно Dispose вызывает Dispose для всех принадлежащих ему объектов-членов. См. Мое второе правило сообщение в блоге для более подробной информации.

...