2015-04-07 3 views
6

Es gibt viele Beispiele für Arrays oder Listen von IDisposable-Objekten, die von Funktionen in .NET zurückgegeben werden. Zum Beispiel Process.GetProcesses().Zu Dispose() oder nicht zu Dispose() Elementen in einem Array von IDisposable-Objekten?

  • Wenn ich diese Methode anrufe, ist es meine Verantwortung für Dispose() aller Mitglieder des Arrays, während ich durch sie iteriere?
  • Warum sollte es meine Verantwortung sein, da ich nie die Objekte erstellt habe und das Array, das mir gegeben wurde, ist nur ein Zeiger auf die Objekte, die außerhalb meines Codes erstellt wurden.
  • Ich dachte immer, es war die Last des Schöpfers zu Dispose(). Also, was ist die richtige Regel hier?

    +0

    Es gibt keine Möglichkeit für den "Ersteller", sie oder Teile in diesen Klassen zu entsorgen, da es keinen Destruktor gibt. Sie haben keine Kontrolle darüber, dass Sie eine Variable auf nichts setzen, um dann das Objekt oder den Inhalt, der entsorgt werden muss, zu entsorgen. – OneFineDay

    +0

    Sicher, Sie können für Process.GetProcesses() ein internes Array aller Process() -Objekte behalten, die Sie jemals an Aufrufer zurückgegeben haben, und dann regelmäßig überprüfen, ob Sie der einzige sind, der einen Verweis auf das Objekt hat Dispose() – Denis

    +3

    @Denis Das Bestimmen, ob jemand anderes einen Verweis darauf hat, ist nicht etwas, was Sie tatsächlich tun können. – Servy

    Antwort

    7

    Es gibt keine allgemeine Regel. Es hängt von der Situation und davon ab, wie die betreffende Methode entwickelt wird, ob "Sie" für die Entsorgung von Objekten verantwortlich sind, zu denen Sie Zugriff haben. Hier ist die Dokumentation oft wichtig, um den Benutzern des Typs zu helfen, ihre Verantwortlichkeiten zu verstehen.

    Ich dachte immer, es der Schöpfer der Last Dispose() war

    Dies kann nicht ganz richtig sein. Es ist manchmal der Fall, dass ein entsorgbares Objekt die Lebensdauer des Codeblocks, der es erstellt, überlebt. Während es einfachste wenn der Schöpfer kann entsorgen das Objekt, manchmal ist es einfach unmöglich für sie zu können. Wenn ein Einwegobjekt von einer Methode zurückgegeben wird, ist es oft nicht möglich, dass der Code, der das Einwegobjekt erstellt, es aufräumt, da seine Lebensdauer kleiner als als die Lebensdauer des Einwegobjekts sein muss.

    +0

    Ich kann ein Einwegobjekt erstellen, indem ich eines innerhalb der Deklaration eines Verwendungsblocks instanziiere. Wäre ein Verwendungsblock nicht genau das, was das löst? Die Lebensdauer des Methodenaufrufs beim Erstellen des Wegwerfobjekts ist kleiner als das eigentliche Wegwerfobjekt selbst ...? Wenn dies nicht der Fall ist und ich den Punkt vermisse, kann ich Sie davon überzeugen, Ihrer Antwort ein Beispiel (sogar ein künstliches) hinzuzufügen? –

    +0

    Meine Güte, ich lese keine Dokumentation, die sorgfältig für jede Klasse, die ich benutze. Bist du sicher, dass es keine Regel gibt? – Denis

    +0

    @Denis, nein, es gibt keine Regel für diese Situation. Sie sollten es selbst entscheiden. – VMAtm

    0

    Die Regel ist sehr einfach: Wenn Sie denken, dass andere Programme Ihre IDisposables verwenden, dann zerstören Sie sie nicht. Ansonsten, mach es.

    Zum Beispiel: GetProcesses() gibt andere Prozesse zurück, die potentiell von anderen Programmen verwendet werden, also sollten Sie nicht ihnen entsorgen.

    Von anderer Seite Dateien, die Sie geöffnet haben sollten für andere Prozesse in OS freigegeben werden, so sollten Sie Wrapper-Streams über sie (sagen wir, sollten Sie entsorgen Dampf zurück durch File.Open-Methode) schließen und entsorgen.

    aktualisieren:
    From MSDN:

    • DO die Grund Entsorgen Muster auf Typen implementieren Instanzen von Einweg-Typen enthalten. Einzelheiten zum Basismuster finden Sie im Abschnitt des Basis-Disposemusters. Wenn ein Typ für die Lebensdauer von anderen Einwegobjekten verantwortlich ist, benötigen die Entwickler auch einen Weg, um von ihnen zu entsorgen. Mit der Dispose-Methode des Containers ist es möglich dies zu ermöglichen.
      • DO die Grund Entsorgen Muster implementieren und einen Finalizer auf Arten halten Ressourcen bereitzustellen, müssen explizit befreit werden und dass nicht über Finalizers.
        Zum Beispiel sollte das Muster auf Typen implementiert werden, die nicht verwaltete Speicherpuffer speichern. Der Abschnitt Finalizable Types behandelt Richtlinien, die sich auf Implementieren von Finalizern beziehen.
      • CONSIDER Implementierung des Basic Dispose Patterns für Klassen, die selbst keine nicht verwalteten Ressourcen oder Einwegobjekte enthalten, aber Subtypen haben, die dies tun.
    +0

    aber wenn ich sie nicht zerstöre, lasse ich Griffe herumschweben ... Also sollte ich sie zerstören? Glauben Sie, dass die zurückgegebenen Process() - Objekte freigegeben sind? Ich wette, dass sie für jede Anforderung von Process.GetProcesses() neu erstellt werden und wenn Sie Dispose nicht hätten, hätten Sie wahrscheinlich ein Handle-Leck ... – Denis

    +0

    Prozesse - nein, sollten Sie nicht (wenn Sie sie nicht erstellen) . Bilder oder Dateien oder ähnliches - ja, du solltest. – VMAtm

    +0

    "Ich lasse Griffe schweben herum" - sie werden finalisiert werden, so ist es in Ordnung – Vlad

    1

    Mit relativ wenigen Ausnahmen (von denen die meisten als die am wenigsten schädlichen Ansätze zum Umgang mit schlecht entworfenem Code beschrieben werden können, die nicht geändert werden können), sollte jede Instanz zu genau einem Zeitpunkt genau eine Instanz haben wohldefinierter Besitzer. In Fällen, in denen eine Methode einen Typ zurückgibt, der IDisposable implementiert, gibt der Vertrag für die Methode an, ob die Methode den Besitz aufgibt (in diesem Fall sollte der Aufrufer sicherstellen, dass das Objekt entsorgt wird) den Besitz an jemand anderen abzugeben), oder ob die Methode lediglich einen Verweis auf ein Objekt zurückgibt, das einer anderen Person gehört.

    In ordnungsgemäß geschriebenen Code ist die Frage, ob ein Objekt entsorgt werden sollte ist selten ein Urteilsspruch. Der Eigentümer eines Objekts sollte sicherstellen, dass es entsorgt wird; niemand sonst sollte es entsorgen. Gelegentlich kann es erforderlich sein, dass eine Methode einen Parameter akzeptiert, der angibt, ob die Methode den Besitz einer IDisposable übertragen soll. Zum Beispiel, wenn der Code einen Sound erzeugen will, ihn an eine "start playing sound" -Methode weitergibt, und sich nie wieder mit diesem Sound beschäftigen will, ist es am einfachsten den Code zu haben, um den Sound accept zu übernehmen und zu entsorgen klingen, wenn es fertig ist; Wenn der Code jedoch wiederholt einen Ton abspielen und sicherstellen möchte, dass das Klangobjekt so lange am Leben bleibt, wie es benötigt wird, wäre es praktischer, wenn der Klangcode nicht übernehmen würde. Die Verwendung separater Methoden kann in gewisser Weise sauberer sein, aber die Verwendung eines Parameters kann die Kapselung unterstützen.

    Im Allgemeinen, wenn der Code eine Liste von Objekten zurückgibt, die IDisposable, der Zweck des Codes implementieren zu Objekte identifizieren, ohne in ihnen jede Beteiligung zu vermitteln. In Abwesenheit eines Eigentumsrechts sollte Code, der solch eine Liste empfängt, nicht Anruf Dispose auf ihm sein.

    Verwandte Themen