Schauen wir uns die berüchtigten IDisposable-Schnittstelle einen Blick:Warum IDisposable-Implementierung ist die Art und Weise entwickelt, es ist
[ComVisible(true)]
public interface IDisposable
{
void Dispose();
}
und einer typischen Implementierung, wie von MSDN empfohlen (weggelassen ich die Prüfung, ob Strom Objekt bereits angeordnet worden):
public class Base : IDisposable
{
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// release managed
}
// release unmanaged
disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Base()
{
Dispose(false);
}
}
public class Derived : Base
{
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
// release managed
}
// release unmanaged
disposed = true;
}
}
Problem ist: Ich denke diese Implementierung ist kontraintuitiv. Und es unterscheidet sich auch signifikant in der Basis- und abgeleiteten Klasse. Abgeleitete Klasse soll annehmen, dass diese Basisklasse IDisposable ordnungsgemäß implementiert und dann Dispose (Bool) überschreiben, die nicht einmal ein Teil der ursprünglichen Schnittstelle ist.
Ich muss zugeben, dass ich diese Frage hatte, weil ich normalerweise Junior-Programmierer anfordere, IDisposable in einem Vorstellungsgespräch zu implementieren. Wenn sie nicht genau wissen, wie es soll getan werden, kommen sie mit etwas in der Nähe auf den Punkt:
public class Base : IDisposable
{
public virtual void Dispose()
{
// release managed and unmanaged
GC.SuppressFinalize(this);
}
~Base()
{
// release unmanaged
}
}
public class Derived : Base
{
public override void Dispose()
{
// release managed and unmanaged
base.Dispose();
}
~Derived()
{
// release unmanaged
}
}
Für mich ist diese Umsetzung klarer und konsistenter ist. Natürlich ist das Schlimme daran, dass wir nicht verwaltete Ressourcen an zwei verschiedenen Stellen freigeben müssen. Wichtig ist jedoch, dass wahrscheinlich über 99% der benutzerdefinierten Klassen nicht verwaltet werden, sodass sie keinen Finalizer benötigen. Ich kann einem Junior-Programmierer nicht erklären, warum MSDN-Implementierung besser ist, weil ich es selbst nicht wirklich verstehe.
Also frage ich mich, was zu so ungewöhnlichen Design-Entscheidungen führte (abgeleitete Klasse, um eine andere Methode als die in der Schnittstelle zu überschreiben und ihn über nicht verwaltete Ressourcen nachzudenken, die es höchstwahrscheinlich nicht enthält). Irgendwelche Gedanken zu diesem Thema?
Falsch. Wenn Sie Ressourcen verwaltet haben, sollten Sie IDisposable weiterhin implementieren und sie verwerfen. – SLaks
Nicht immer wahr. Sie kapseln möglicherweise einen Typ mit nativen Ressourcen oder implementieren einen faktorierten Typ. –
@SLaks: Wenn die Ressourcen vollständig verwaltet werden, ist dies weniger wichtig (da ein vollständig verwalteter Typ vom GC korrekt gehandhabt wird) –