Какой класс «владеет» неуправляемым ресурсом (и какой реализует IDisposable)?

StackOverflow https://stackoverflow.com//questions/9657637

Вопрос

Я работаю на проект ОСС сделать популярным Библиотека МедиаИнфо проще использовать в .NET, но этот вопрос можно обобщить.

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

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

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

Д происходит от БД:

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

БД устанавливает унаследованный О, полученный из Б:

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

Б заявляет О:

// StreamBaseClass is "B"
public abstract class StreamBaseClass
{
    protected MediaInfo mediaInfo; // "O" is declared
    // ...
}
Это было полезно?

Решение

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

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

Другие советы

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

Если класс D владеет собственным ресурсом n, то D должен быть idisposable (который удаляет n) и должен также иметь доказательную деструксор, который вызовов вызовов () на себя, чтобы освободить n.

.

Если вы будете следовать этому шаблону, то если у вас когда-либо имели idisposable, вы всегда должны распоряжаться (), когда вы закончите, и это будет удалять все, что все вниз по дереву объекта;Но и если кто-то забывает вам (читать: коллега, пользователь вашей библиотеки и т. Д.) Не будет терять любые объекты, потому что нативный ресурс будет очищен заканчивом DIALIZER.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top