Какой класс «владеет» неуправляемым ресурсом (а какой реализует IDisposable)? - PullRequest
2 голосов
/ 11 марта 2012

Я работаю над проектом OSS , чтобы упростить использование популярной библиотеки MediaInfo в .NET, но этот вопрос можно обобщить.

Еслипроизводный класс D всегда создает экземпляр объекта O при вызове конструктора его базового класса DB .DB устанавливает свое значение равным тому, которое отправлено его конструктору, но само значение объявлено в DB базовом классе B :

  1. Кто "владеет" O (AKA mediaInfo в приведенном ниже коде)?
  2. В случае приложения .NET, какое из них должно реализовывать IDisposable?Примечание: O неуправляемо или, по крайней мере, является экземпляром управляемого объекта, обернутого вокруг неуправляемой библиотеки, но требует очистки в виде " MediaInfo.Close (); ",Я не уверен, что это считается «неуправляемым».

Чтобы пояснить, позвольте мне использовать фактический код:

D происходит от DB :

// MediaFile is "D" 
public sealed class MediaFile : GeneralStream
{
    public MediaFile(string filePath)
        : base(new MediaInfo(), 0) {
        // mediaInfo is "O"
        mediaInfo.Open(filePath);
    }
}

DB устанавливает его унаследованные O , полученные из B :

// GeneralStream is "DB"
public abstract class GeneralStream : StreamBaseClass
{
    public GeneralStream(MediaInfo mediaInfo, int id) {
        this.mediaInfo = mediaInfo; // declared in StreamBaseClass
        // ...
    }
}

B объявляет O :

// StreamBaseClass is "B"
public abstract class StreamBaseClass
{
    protected MediaInfo mediaInfo; // "O" is declared
    // ...
}

Ответы [ 3 ]

2 голосов
/ 11 марта 2012

Объект, который содержит ссылку на ресурс, владеет им.

StreamBaseClass имеет ссылку mediaInfo и должен реализовать IDisposable.Ссылка и метод Dispose будут автоматически наследоваться производными классами.

1 голос
/ 12 марта 2012

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

Что касается вашего конкретного случая, то создание IDisposable в цепочечном вызове конструктора является рецептом для утечек ресурсов (поскольку нет способа обернуть цепочечные вызовы конструктора в блок try-finally). Если бы вы как-то обрабатывали это безопасно (например, используя фабричный метод, а не цепочечный конструктор или взлом [threadstatic]), я бы предположил, что, поскольку создатель объекта (производный класс) будет знать Время жизни потребителя (базовый класс), ответственность за владение и очистку должны оставаться за создателем объекта.

1 голос
/ 11 марта 2012

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

Если класс D владеет собственным ресурсом N, тогда D должен быть IDisposable (который удаляет N), а также должен иметь финализируемый деструктор, который вызывает Dispose () для себя, чтобы освободить N.

Если вы следуете этому шаблону, то, если у вас когда-либо будет IDisposable, вы всегда должны использовать Dispose (), когда закончите, и это удалит все на всем протяжении дерева объектов; но также, если кто-то забудет вас (читай: коллега, пользователь вашей библиотеки и т. д.), не будет утечка каких-либо объектов, потому что собственный ресурс будет очищен финализатором D.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...