Beginnen Sie mit diesen einfachen Klassen ...
Angenommen, ich habe eine einfache Reihe solcher Klassen:
class Bus
{
Driver busDriver = new Driver();
}
class Driver
{
Shoe[] shoes = { new Shoe(), new Shoe() };
}
class Shoe
{
Shoelace lace = new Shoelace();
}
class Shoelace
{
bool tied = false;
}
A Bus
hat a Driver
, das Driver
hat zwei Shoe
s, jeder Shoe
hat a Shoelace
. Alles sehr dumm.
Fügen Sie Shoelace ein IDisposable-Objekt hinzu
Später entscheide ich, dass eine Operation auf dem Shoelace
Multithreading ausgeführt werden kann, also füge ich eine hinzu, EventWaitHandle
mit der die Threads kommunizieren können. So Shoelace
sieht es jetzt aus:
class Shoelace
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
// ... other stuff ..
}
Implementieren Sie IDisposable auf Shoelace
Jetzt beschwert sich Microsoft FxCop jedoch: "Implementieren Sie IDisposable auf 'Shoelace', da Mitglieder der folgenden IDisposable-Typen erstellt werden: 'EventWaitHandle'."
Okay, ich implementiere IDisposable
weiter Shoelace
und meine nette kleine Klasse wird zu diesem schrecklichen Durcheinander:
class Shoelace : IDisposable
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Shoelace()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
if (waitHandle != null)
{
waitHandle.Close();
waitHandle = null;
}
}
// No unmanaged resources to release otherwise they'd go here.
}
disposed = true;
}
}
Oder (wie von Kommentatoren hervorgehoben), da es Shoelace
selbst keine nicht verwalteten Ressourcen gibt, könnte ich die einfachere Entsorgungsimplementierung verwenden, ohne den Dispose(bool)
und Destructor zu benötigen :
class Shoelace : IDisposable
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
public void Dispose()
{
if (waitHandle != null)
{
waitHandle.Close();
waitHandle = null;
}
GC.SuppressFinalize(this);
}
}
Beobachten Sie entsetzt, wie sich IDisposable ausbreitet
Richtig, das ist behoben. Aber jetzt wird sich FxCop beschweren, dass ein Shoe
schafft Shoelace
, so Shoe
muss es IDisposable
auch sein.
Und Driver
schafft muss Shoe
so Driver
sein IDisposable
. Und Bus
schafft Driver
so Bus
muss sein IDisposable
und so weiter.
Plötzlich verursacht meine kleine Änderung an Shoelace
viel Arbeit und mein Chef fragt sich, warum ich zur Kasse gehen muss Bus
, um eine Änderung vorzunehmen Shoelace
.
Die Frage
Wie verhindern Sie diese Ausbreitung IDisposable
und stellen dennoch sicher, dass Ihre nicht verwalteten Objekte ordnungsgemäß entsorgt werden?