C #: каким должно быть содержимое метода Dispose при реализации интерфейса IDisposable - PullRequest
4 голосов
/ 18 февраля 2011

Я создал класс, который реализует IDisposable интерфейс, и VisualStudio IDE принес мне метод Dispose.Мне интересно, какой код я должен написать внутри метода Dispose, чтобы он позаботился об управлении моей памятью или о том, что он должен делать.

public class ESNVerification : IDisposable 
{ 

  public bool Save(string a,string b)
  {
    //Save the data to table
    return true;
  }

  public void Dispose()
  {
       throw new NotImplementedException();
       // Really what i should do here  ?
  }
}

Ответы [ 9 ]

3 голосов
/ 19 февраля 2011

Я рекомендую Три простых правила о том, как реализовать IDisposable; здесь упрощенно:

  • Правило 1: не делайте этого (если вам не нужно). Есть только две ситуации, когда IDisposable необходимо реализовать: Класс владеет неуправляемым ресурсом или Класс владеет управляемыми (IDisposable) ресурсами .
  • Правило 2: Для класса, владеющего управляемыми ресурсами, реализуйте IDisposable (но не финализатор). Эта реализация IDisposable должна вызывать Dispose только для каждого собственного ресурса. У класса не должно быть финализатора.
  • Правило 3: Для класса, владеющего одним неуправляемым ресурсом, реализуйте IDisposable и финализатор.
2 голосов
/ 18 февраля 2011

Если вы не работаете с какими-то неуправляемыми ресурсами, которые необходимо очистить (а в этом крайне простом случае это не так), то у вас действительно нет причин для реализации IDisposable.

Первая строка в MSDN Описание интерфейса IDisposable:

Основное использование этого интерфейса освободить неуправляемые ресурсы

Если вы использовали неуправляемые ресурсы, то в методе Dispose вы должны обеспечить правильное освобождение этих ресурсов (сборщик мусора позаботится обо всех ваших управляемых ресурсах за вас).

1 голос
/ 20 февраля 2011

В 99% случаев среда Microsoft сильно усложняется, и правильный подход прост:

  1. Если в вашем классе есть какие-либо поля типов, реализующие IDisposable, и никто не собирается ожидать использованияКогда вы закончите с этими объектами, вы должны реализовать IDisposable, и ваш метод удаления должен вызвать Dispose для всех таких полей.
  2. Если в вашем классе нет таких полей, но вы думаете, что классы, производные от ваших, могут или если вашему классу требуется реализовать интерфейс, такой как IEnumerator (of T), для которого требуется IDisposable, у вас должен быть переопределяемый метод Dispose, который ничего не делает,
  3. Надлежащая семантика для метода «dispose» состоит в том, чтобы объект делал все необходимое для очистки других объектов до того, как от него отказались.Если объект не должен очищать другие объекты, утилизация не должна безвредно ничего не делать.Нет никаких причин для исключения NotImplementedException или NotSupportedException из Dispose.

Ключевым моментом при реализации IDisposable является не очистка какого-либо конкретного вида "ресурсов", а скорее обеспечение того, что если объект изменяет других объектов в системе таким образом, чтобыкогда-нибудь потребуется очистка, эти объекты будут очищены, пока информация и стимул, необходимые для этого, все еще существуют.В идеале эта очистка должна произойти как можно скорее, но не раньше.Если объект содержит, например, ничего, кроме набора строк, очистка не требуется.Строка не требует очистки;массив объектов, не требующих очистки, не требует никакой очистки, а объект, содержащий только объекты, не требующие очистки, также не требует очистки.С другой стороны, действие, такое как открытие сокета TCP, создает необходимость обеспечить выполнение определенного действия по очистке (закрытие сокета).Если объект открывает TCP-сокет и хранит информацию о нем, цель вызова Dispose для этого объекта состоит не в том, чтобы уничтожить информацию о сокете (об этом позаботится сборщик мусора), а в том, чтобы обеспечить необходимоевыполняется операция «close» в стеке TCP.

1 голос
/ 18 февраля 2011
1 голос
/ 18 февраля 2011

Утилизация предназначена для освобождения неуправляемых ресурсов (то есть ресурсов, которые не используются автоматически сборщиком мусора после использования). Типичными примерами являются соединения с базой данных и файлами. Реализация метода удаления предоставляет дополнительные пояснения и пример кода.

На этой странице есть важное предупреждение о том, что метод Dispose должен быть реализован таким образом, чтобы несколько вызовов не вызывали исключение. Это потому, что он используется сборщиком мусора и может вызывать метод dispose несколько раз.

0 голосов
/ 20 февраля 2011

Есть только две причины для реализации IDisposable 1 , и то, что вы делаете внутри метода Dispose, зависит от того, какой из них применим к вашей ситуации.

Если ваш класс создает объектэкземпляры, которые реализуют IDisposable и не могут избавиться от них в методе, который их создает, этот класс будет иметь переменные-члены, которые ссылаются на эти экземпляры.Этот класс также должен реализовывать IDisposable, и внутри него вы должны вызывать Dispose для каждого доступного члена.

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

1 Если только вы не сознательно используете IDisposable нестандартным способом .(Хотя достоинства этого спорны .)

0 голосов
/ 18 февраля 2011

Существует метод dispose, позволяющий освободить любые выделенные ресурсы, которые не являются простыми объектами (которые очищаются сборкой мусора). Например

  • потоки
  • соединения с базой данных и / или наборы результатов
  • указатели на неуправляемые объекты
  • любой объект, выделенный внутри вашего объекта, который также реализует IDisposable

следует очистить в вашем методе Dispose (возможно, вызвав Dispose для этих объектов).

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

0 голосов
/ 18 февраля 2011

Шаблон IDisposable следует использовать, когда ваш класс использует неуправляемые системные ресурсы, например, для обработки файлов, указателей ... Чтобы освободить используемую память.

Если ваш класс не использует неуправляемые ресурсы, онвероятно, не нужно использовать этот шаблон.

Если вам действительно нужен IDisposable:

public void Dispose()
{
  //Free here your resources

  this.Dispose(true);
  GC.SuppressFinalize(this);
}
0 голосов
/ 18 февраля 2011

На MSDN есть две довольно приличные статьи: Реализация метода Dispose и Реализация Finalize и Dispose для очистки неуправляемых ресурсов . Заметив, что первый говорит:

Нет никакого выигрыша в производительности при реализации метода Dispose для типов, которые используют только управляемые ресурсы (например, массивы), поскольку они автоматически возвращаются сборщиком мусора.

Я бы порекомендовал вам прочитать оба, решить, нужно ли вам это реализовать, и использовать примеры кода там для начала.

...