2015-07-20 6 views
5

Ich arbeite an einem großen Projekt in C# .NET 4.0. Es gibt eine benutzerdefinierte Klasse, die von der Klasse System.Net.Sockets.SocketAsyncEventArgs geerbt wurde. Etwas wie folgt aus:Wie IDisposable-Schnittstelle in einer Klasse implementiert, die von SocketAsyncEventArgs geerbt wird

public class SocketTaskArgs : SocketAsyncEventArgs 
{ 
    public SocketTaskArgs() 
    { 
     Completed += someEventhHandler; 
    } 

    public void CleanUp() 
    { 
     Completed -= someEventhHandler; 
    } 

    /* 
     There is a lot of code here that is unimportant at the moment. 
    */ 
} 

So wollte ich den Inhalt von CleanUp() -Methode bewegen Verfügungs (bool) -Methode.

Als erstes, überprüfte ich den Quellcode der Basisklasse - SocketAsyncEventArgs (mit Go To Definition so dass ich Metadaten als Quelle gesehen). Ich fand heraus, diese Klasse implementiert IDisposable-Schnittstelle. Schön, ich muss nur die Dispose (bool) -Methode außer Kraft setzen, oder? (Siehe "IDisposable Interface on MSDN", "IDisposable und die Vererbungshierarchie" für weitere Details). Nichts Neues für mich ... Leider ist die SocketAsyncEventArgs Klasse wie folgt umgesetzt:

public class SocketAsyncEventArgs : EventArgs, IDisposable 
{ 
    public void Dispose(); 

    //some other stuff here 
} 

Das heißt, es gibt keinen Weg, wie Dispose (bool) Methode außer Kraft zu setzen, da es als privaten implementiert ist statt von geschützt ... Was ist der Grund dafür?

Als nächstes lese ich über SocketAsyncEventArgs.Dispose() Methode auf MSDN. Das Komische ist, dass es den folgenden Abschnitt enthält:

Hinweise

Entsorgen zur Vererbung kann mehrfach von anderen Objekte aufgerufen werden. Beim Überschreiben Dispose (Boolean), seien Sie vorsichtig, keine Objekte zu referenzieren, die zuvor in einem früheren Anruf zu Dispose entsorgt wurden. Weitere Informationen zum Implementieren von Dispose (Boolean), finden Sie unter Implementieren einer Dispose-Methode.

Warten ... was?

Wenn zwingende Dispose (Boolean), ...

Wie soll ich Dispose (Boolean) außer Kraft zu setzen?

Was ist die empfohlene Methode zur Implementierung der IDisposable-Schnittstelle in diesem Fall?

+1

Es ist nicht privat, es ist überhaupt nicht implementiert (siehe http://referencesource.microsoft.com/System/net/System/Net/Sockets/Socket.cs.html#8877). Es verwendet einen Finalizer, sieht aber so aus, als ob er nicht im empfohlenen Muster implementiert wurde. –

+0

Es scheint, als wäre "Dispose" öffentlich, nur nicht "virtuell". –

+0

Sie sollen nicht von dieser Klasse erben. Das kann man in einem großen bestehenden Projekt wahrscheinlich nicht so einfach ändern. – usr

Antwort

3

Es scheint nichts hindert Sie daran zu sein IDisposable auf Ihrem Kind Klasse Umsetzung, nehmen Sie dieses Beispiel:

public class DisposableParent : IDisposable 
{ 
    public void Dispose() 
    { 
     Console.WriteLine("The parent was disposed."); 
    } 
} 

public class DisposableChild : DisposableParent, IDisposable 
{ 
    public new void Dispose() 
    { 
     base.Dispose(); 
     Console.WriteLine("The child was disposed."); 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     using (DisposableChild c = new DisposableChild()) { } 
     Console.ReadKey(true); 
    } 
} 

gibt die folgende Ausgabe:

Die Mutter angeordnet wurde.

Das Kind wurde entsorgt.

Der Compiler warnt vor der dispose der Elternklasse in dem Kind versteckt, so den new Operator wird von dieser Warnung los zu werden, so stellen Sie sicher Dispose von der Kind-Klasse die Basisklasse zu nennen (und implementieren sie die richtiger Weg).

Die dispose für das Kind würde so etwas geworden:

public class DisposableChild : DisposableParent, IDisposable 
{ 
    private bool _disposed = false; 

    public new void Dispose() 
    { 
     Dispose(true); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      if (!_disposed) 
      { 
       base.Dispose(); 
       Console.WriteLine("The child was disposed."); 
       _disposed = true; 
      } 
     } 
    } 
} 

Und ja, das funktioniert immer noch, wenn Sie so etwas tun:

using (DisposableParent p = new DisposableChild()) 
{ 

} 

Aber so etwas wie dieses kann es brechen:

public class Program 
{ 
    public static void Main() 
    { 
     DisposableChild c = new DisposableChild(); 
     DisposeOfIt(c); 

     Console.ReadKey(true); 
    } 

    public static void DisposeOfIt(DisposableParent p) 
    { 
     p.Dispose(); 
    } 
} 

Es wird nur ausgedruckt, dass der Elternteil entsorgt wurde. Wenn Sie diese Methode verwenden, müssen Sie vorsichtig sein, um die Lebensdauer Ihrer Objekte zu kontrollieren.

+0

Danke für die Antwort. Ich stimme Ihnen zu, dass ich die IDisposable-Schnittstelle für meine geerbte Klasse implementieren kann. Das war das erste, was mir in den Sinn kam. Ich bin nur neugierig, ob jemand mit einer anderen und vielleicht einer besseren Idee kommt. Wenn es in naher Zukunft nichts Besseres gibt, werde ich Ihre Antwort als akzeptiert markieren. –

Verwandte Themen