Базовый класс DisposableObject для C#


Я часто столкнуться с необходимостью реализации IDisposable в мой код. Чтобы правильно распоряжаться как управляемые, так и неуправляемые ресурсы, требует разумное количество boilerplate кода. На основе документации нашел здесь я создал следующий базовый класс.

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

Разве это правильно? И кто-нибудь написал нечто подобное? Буду признателен за замечания по стилю, правильности и как хорошо это соответствует лучшей практике.

public abstract class DisposableObject : IDisposable
{
    private bool _disposed = false;

    public bool Disposed
    {
        get { return _disposed; }
    }

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

    ~DisposableObject()
    {
        Dispose(false);
    }

    private void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                DisposeManagedResources();
            }

            DisposeUnmanagedResources();

            _disposed = true;
        }
    }

    protected abstract void DisposeManagedResources();
    protected abstract void DisposeUnmanagedResources();
}

Редактировать: окончательной реализации

public abstract class DisposableObject : IDisposable
{
    public bool Disposed { get; private set;}      

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

    ~DisposableObject()
    {
        Debug.Assert(Disposed, "WARNING: Object finalized without being disposed!");
        Dispose(false);
    }

    private void Dispose(bool disposing)
    {
        if (!Disposed)
        {
            if (disposing)
            {
                DisposeManagedResources();
            }

            DisposeUnmanagedResources();
            Disposed = true;
        }
    }

    protected virtual void DisposeManagedResources() { }
    protected virtual void DisposeUnmanagedResources() { }
}


4234
32
задан 31 мая 2011 в 12:05 Источник Поделиться
Комментарии
5 ответов

Я бы подумала О внесении двух изменений:


  1. Сделать одну или обе распоряжаться*ресурсы методы виртуальные, а не абстрактные. Хотя это сильно зависит от того, как часто вы должны обращаться неуправляемые ресурсы. Я не могу вспомнить последний раз, когда я был в обращении с ними и я бы не переопределить этот метод в каждом классе просто сделать его пустым.

  2. Я хотел бы добавить некоторые лесозаготовки либо на свой финализатор способ или метод Dispose(bool утилизации) метод для того, чтобы поймать ситуациях, когда удаляемый объект не утилизировать правильно, вызвав метод Dispose() метод. Большинство разработчиков ищут такую информацию и у вас есть хорошее место, чтобы впрыснуть его.

14
ответ дан 31 мая 2011 в 08:05 Источник Поделиться

Что-то я нашел полезным в прошлом, при реализации данного шаблона является захват трассировку стека во время строительства, и включить это в отладке.Утвердить сообщение.

Зная, где был создан объект часто может быть помочь в поиске источника проблемы, особенно если объекты создаются в одном месте, а затем должны быть удалены по каким-либо другим объектом, который берет на себя ответственность за свою жизнь.

10
ответ дан 2 июня 2011 в 09:06 Источник Поделиться

Я согласен с Брайаном, за исключением того, что я считаю, что метод Dispose(bool утилизации) метод должен быть абстрактным. Моя логика, заключается в том, что вы должны иметь основания для наследования от DisposableObject типа, в первую очередь, в этом случае, имея метод как виртуальный, кажется, немного бессмысленно, так как это будет необязательный реализации. Если он не является обязательным, поэтому унаследовал от DisposableObject в любом случае?

Имея его в качестве виртуального будет выгодно, где у вас есть некоторые общие код, но, возможно, лучшим решением будет:

protected virtual void Dispose(bool disposing)
{
if (!Disposed)
{
DisposeInternal(disposing);
Disposed = true;
}
}

protected abstract void DisposeInternal(bool disposing);

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

6
ответ дан 2 июня 2011 в 06:06 Источник Поделиться

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

Если вы все еще хотите использовать два метода, я бы предложил сделать хотя-бы DisposeUnmanagedResources() виртуальной, а не абстрактные как удобство наследникам. Я считаю, это гораздо более общим для моей одноразовыми предметами распоряжаться другие объекты, а не очистки неуправляемых собственных ресурсов.

3
ответ дан 31 мая 2011 в 03:05 Источник Поделиться

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

Необходимо очень тщательно выполнить финализаторы; это сложная операция, которая может нести значительные накладные расходы.

3
ответ дан 27 июня 2012 в 12:06 Источник Поделиться