Domanda

Sto lavorando su un progetto OSS per rendere il famoso MediaInfo biblioteca più facile da usare in .NET, ma questa domanda è generalizzabile.

Se una classe derivata D sempre crea un'istanza di un oggetto O quando si chiama la classe base DB's costruttore.DB imposta il suo valore, che ha inviato al suo costruttore, ma il valore stesso è dichiarato in DB's classe base B:

  1. Chi "possiede" O (AKA mediaInfo nel codice riportato di seguito)?
  2. Nel caso di un .NETTO domanda, a quale di questi implementa IDisposable?Nota: O non gestito, o almeno è un'istanza di un oggetto gestito avvolto intorno a una libreria non gestita, ma ha bisogno di pulizia in forma di "MediaInfo.Close();".Non sono sicuro questo conta come "non gestito."

Per chiarire, mi permetta di utilizzare il codice vero e proprio:

D deriva da DB:

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

DB imposta il suo ereditato O, derivato da B:

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

B dichiara O:

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

Soluzione

L'oggetto, che detiene un riferimento alla risorsa, lo possiede.

StreamBaseClass ha il riferimento mediaInfo e dovrebbe implementare IDisposable.Il riferimento e il metodo Dispose verranno automaticamente ereditati dalle classi derivanti.

Altri suggerimenti

Se una classe C possiede una variabile che è a non esposta a Variabile locale V che implementa idisponibile, quindi c deve essere idisponibile e IDisponibile IDisponibile dovrebbe disporre v.

Se una classe D possiede una risorsa nativa n, quindi D dovrebbe essere idisponibile (che elimina n) e dovrebbe anche ha un distruttore finalizzabile che chiamano smaltire () su se stesso a rilasciare n.

.

Se segui questo schema, allora se hai mai avuto un idisponibile, dovresti sempre disporre () quando hai finito e che eliminerà tutto il modo in giù per l'albero degli oggetti;Ma anche se qualcuno ti dimentica (leggi: un collega, utente della tua biblioteca ecc.) Non perderanno oggetti perché la risorsa nativa verrà ripulita da D'S finalizer.

La responsabilità di un IDisposable appartiene all'oggetto che crea esso, in assenza di esplicito accordo in altro modo.Contrariamente accordi sono generalmente utilizzati nei casi in cui il creatore di una risorsa può non avere idea di consumatore vita.Vorrei suggerire che, in molti casi, quando un costruttore o metodo factory è la produzione di quello che potrebbe essere l'ultimo consumatore di un passato IDisposable, che metodo dovrebbe accettare un parametro che indica se si deve accettare la responsabilità per la chiamata di Dispose, oppure accettare un delegato di richiamata che, se non nullo, essere invocato quando il consumatore non ha più bisogno l'oggetto.Se il creatore dell'oggetto trascenderà il consumatore, si può passare null;se il creatore non avrà utilizzare per l'oggetto una volta che è stato consegnato, è possibile passare l'oggetto Dispose metodo.Se il creatore non so se si trascenderà il consumatore, si può passare a un metodo in grado di determinare se l'oggetto è ancora necessario e chiamata Dispose se non.

Per quanto riguarda il tuo caso particolare, la costruzione di un IDisposable all'interno di una incatenato chiamata del costruttore è una ricetta per delle perdite di risorse (poiché non vi è alcun modo per avvolgere incatenato costruttore di chiamate in un try-finally).Se si dovesse in qualche modo gestire in modo sicuro (ad es.utilizzando un metodo factory piuttosto che un incatenato costruttore, o utilizzando un [threadstatic] hack), vorrei suggerire che, poiché il creatore dell'oggetto (la classe derivata) è andare a conoscere il ciclo di vita del consumatore (classe base), la proprietà e la pulizia di responsabilità dovrebbe rimanere con il creatore di oggetti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top