Frage

Ich arbeite an ein OSS-Projekt um das Populäre zu machen MediaInfo-Bibliothek einfacher in .NET zu verwenden, aber diese Frage ist verallgemeinerbar.

Wenn eine abgeleitete Klasse D instanziiert immer ein Objekt Ö beim Aufruf seiner Basisklasse DB's Konstruktor.DB setzt seinen Wert auf den an seinen Konstruktor gesendeten Wert, der Wert selbst wird jedoch in deklariert DBist die Basisklasse B:

  1. Wem gehört" Ö (AKA mediaInfo im Code unten)?
  2. Welche davon sollte im Fall einer .NET-Anwendung IDisposable implementieren?Notiz: Ö ist nicht verwaltet, oder es handelt sich zumindest um eine Instanziierung eines verwalteten Objekts, das um eine nicht verwaltete Bibliothek herum gewickelt ist, aber eine Bereinigung in Form von „MediaInfo.Close();".Ich bin nicht sicher, ob dies als „nicht verwaltet“ gilt.

Zur Verdeutlichung möchte ich den tatsächlichen Code verwenden:

D kommt von DB:

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

DB setzt seine Vererbung Ö, abgeleitet von B:

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

B erklärt Ö:

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

Lösung

Das Objekt, das einen Verweis auf die Ressource enthält, ist deren Eigentümer.

StreamBaseClass hat die Referenz mediaInfo und sollte umgesetzt werden IDisposable.Die Referenz und die Dispose Die Methode wird automatisch von den abgeleiteten Klassen geerbt.

Andere Tipps

Wenn eine Klasse C eine Variable besitzt, die eine nicht exponierte lokale Variable V ist, die idientierbar implementiert, sollte C idispositionbar sein, und Cs idientierbar sollte v.

Wenn eine Klasse D eine native Ressource n besitzt, sollte d idiitierbar sein (welche löscht N) und sollte auch einen finanzierbaren Destruktor haben, der einen finanzierbaren Destruktor haben sollte, der () an sich selbst zum Freigeben von n entsorgen.

Wenn Sie dieses Muster folgen, dann sollten Sie, wenn Sie jemals ein idiformierbar sind, Sie immer entsorgen (), wenn Sie fertig sind, und das löscht alles den ganzen Weg nach unten den Objektbaum.Aber auch wenn jemand an Ihnen vergisst (Lesen: Ein Kollege, Benutzer Ihrer Bibliothek usw.) leckt keine Objekte, da die native Ressource vom D-S-Finalizer aufgeräumt wird.

Die Verantwortung eines IDisposable gehört zu dem Objekt, das schafft es, sofern nicht ausdrücklich etwas anderes vereinbart wurde.Gegenteilige Vereinbarungen werden im Allgemeinen in Fällen verwendet, in denen der Ersteller einer Ressource möglicherweise keine Ahnung von der Lebensdauer des Verbrauchers hat.Ich würde vorschlagen, dass in vielen Fällen, wenn ein Konstruktor oder eine Fabrikmethode den letzten Verbraucher einer übergebenen Methode erzeugt IDisposable, sollte diese Methode einen Parameter akzeptieren, der angibt, ob sie die Verantwortung für den Aufruf übernehmen soll Dispose, oder akzeptieren Sie einen Rückrufdelegierten, der, wenn er nicht null ist, aufgerufen wird, wenn der Verbraucher das Objekt nicht mehr benötigt.Wenn der Ersteller des Objekts den Konsumenten überlebt, kann es null übergeben;Wenn der Ersteller das Objekt nach der Übergabe nicht mehr verwenden kann, kann er es weitergeben Dispose Methode.Wenn der Ersteller nicht weiß, ob es den Konsumenten überleben wird, kann er eine Methode übergeben, die ermittelt, ob das Objekt noch benötigt wird, und sie aufrufen Dispose wenn nicht.

Im Hinblick auf Ihren speziellen Fall ist die Erstellung eines IDisposable innerhalb eines verketteten Konstruktoraufrufs ist ein Rezept für Ressourcenlecks (da es keine Möglichkeit gibt, verkettete Konstruktoraufrufe in einen try-finally-Block einzuschließen).Wenn Sie das irgendwie sicher handhaben würden (z.B.Verwenden einer Factory-Methode anstelle eines verketteten Konstruktors oder mithilfe von a [threadstatic] Hack) würde ich vorschlagen, dass, da der Ersteller des Objekts (die abgeleitete Klasse) die Lebensdauer des Verbrauchers (der Basisklasse) kennt, die Verantwortung für Eigentum und Bereinigung beim Objektersteller verbleiben sollte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top