Как реализовать Dispose на объекте создает другие одноразовые - PullRequest
0 голосов
/ 20 ноября 2018

Учитывая следующий класс:

public class MyDisposableContainer : IDisposable
{
    readonly List<IDisposable> _chidlren = new List<IDisposable>();

    public void Add() => _children.Add(new FileSystemWachter());
}

Я не уверен, как мне реализовать одноразовый интерфейс.

Либо:

 public void Dispose() => _children.ForEach(item => item.Dispose());

или

public void Dispose()
{
    // Dispose of unmanaged resources.
    Dispose(true);
    // Suppress finalization.
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        _children.ForEach(item => item.Dispose());
    }
}

В моем случае дочерними являются FileSystemWatcher, который использует некоторые неуправляемые ресурсы, поэтому я предполагаю, что он реализует одноразовый шаблон вместе с финализатором.

Полагаю, второй, более длинный подход не нужен,потому что это Dispose (true) будет вызываться только при явном вызове Dispose () в любом случае.Я прав?

1 Ответ

0 голосов
/ 20 ноября 2018

Итак, краткий ответ: да, вы можете использовать простую форму

public void Dispose() => _children.ForEach(item => item.Dispose());

в вашем случае.

Расширенная форма

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
       ...
    }
}

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

Более длинный ответ подразумевает прояснение возможных сценариев, связанных с удалением, и лучших практик для этого.Процесс уничтожения объекта имеет дело с двумя типами ресурсов, управляемых и управляемых.Управляемые ресурсы могут быть успешно обработаны GC, поэтому нам, как правило, не стоит слишком сильно беспокоиться об этом, в то время как освобождение неуправляемых ресурсов является обязанностью вызова кода, поскольку GC не может отслеживать их распределение и перераспределение.IDisposable Цель интерфейса - рассмотреть сценарии, когда неуправляемое выделение ресурсов должно обрабатываться в некотором объекте или иерархии объектов.Теперь что касается возможных случаев:

  • , если ваш класс напрямую сохраняет неуправляемые ресурсы, рекомендуется использовать расширенный финализируемый шаблон удаления с финализатором, чтобы покрыть случаи неправильного использования классавнешними потребителями или в исключительных ситуациях, чтобы получить гарантированное перераспределение ресурсов с помощью Dispose или финализатора;
  • , если ваш класс содержит другие IDisposable, но не содержит неуправляемые ресурсы напрямую, рекомендуемый способ:используя базовый шаблон удаления без финализатора;

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

...