Pergunta

Eu estou trabalhando em um projeto OSS para tornar o popular Biblioteca MediaInfo mais fácil de usar no .NET, mas esta questão é generalizável.

Se uma classe derivada D sempre instancia um objeto Ó ao chamar sua classe base BDconstrutor.O banco de dados define seu valor como aquele enviado ao seu construtor, mas o valor em si é declarado em BDclasse base de B:

  1. Quem possui" Ó (AKA mediaInfo no código abaixo)?
  2. No caso de uma aplicação .NET, qual delas deve implementar o IDisposable?Observação: Ó não é gerenciado ou pelo menos é uma instanciação de um objeto gerenciado agrupado em uma biblioteca não gerenciada, mas precisa de limpeza na forma de "MediaInfo.Close();".Não tenho certeza se isso conta como "não gerenciado".

Para ajudar a esclarecer, deixe-me usar o código real:

D deriva de BD:

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

BD define seu herdado Ó, derivado de B:

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

B declara Ó:

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

Solução

O objeto, que contém uma referência ao recurso, é o proprietário dele.

StreamBaseClass tem a referência mediaInfo e deveria implementar IDisposable.A referência e o Dispose método será automaticamente herdado pelas classes derivadas.

Outras dicas

Se uma classe C possui uma variável que é um não exposto variável local V que implementa IDisposable, então C deve ser IDisposable e o IDisposable de C deve descartar V.

Se uma classe D possui um recurso nativo N, então D deve ser IDisposable (que exclui N) e deveria também tem um destruidor finalizável que chama Dispose() para liberar N.

Se você seguir esse padrão, se você tiver um IDisposable, você deve sempre Dispose() usá-lo quando terminar e isso excluirá tudo na árvore de objetos;mas também se alguém se esquecer de você (leia:um colega, usuário de sua biblioteca etc) não vazará nenhum objeto porque o recurso nativo será limpo pelo finalizador de D.

A responsabilidade de um IDisposable pertence ao objeto que cria isso, na ausência de qualquer acordo explícito em contrário.Acordos contrários são geralmente utilizados nos casos em que o criador de um recurso pode não ter ideia da vida útil do consumidor.Eu sugeriria que em muitos casos, quando um construtor ou método de fábrica está produzindo o que pode ser o último consumidor de um método passado IDisposable, esse método deve aceitar um parâmetro indicando se ele deve aceitar a responsabilidade pela chamada Dispose, ou então aceite um delegado de retorno de chamada que, se não for nulo, será invocado quando o consumidor não precisar mais do objeto.Se o criador do objeto sobreviver ao consumidor, ele poderá passar nulo;se o criador não tiver utilidade para o objeto depois que ele for entregue, ele poderá passar o objeto Dispose método.Se o criador não souber se sobreviverá ao consumidor, ele poderá passar um método que determinará se o objeto ainda é necessário e chamar Dispose se não.

No que diz respeito ao seu caso particular, construir um IDisposable dentro de uma chamada de construtor encadeada é uma receita para vazamentos de recursos (já que não há como agrupar chamadas de construtor encadeadas em um bloco try-finalmente).Se você de alguma forma lidasse com isso com segurança (por exemplo,usando um método de fábrica em vez de um construtor encadeado, ou usando um [threadstatic] hack), eu sugeriria que, como o criador do objeto (a classe derivada) saberá o tempo de vida do consumidor (a classe base), a propriedade e a responsabilidade pela limpeza deveriam permanecer com o criador do objeto.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top