Ist das Microsoft IDisposable-Muster tatsächlich korrekt?C#

Ein Treffpunkt für C#-Programmierer
Guest
 Ist das Microsoft IDisposable-Muster tatsächlich korrekt?

Post by Guest »

Ich bin schon oft über die von Microsoft empfohlene Methode zum Implementieren des IDisposable-Musters gestolpert. In Visual Studio ist es sogar als Option „Schnittstelle implementieren“ im Lampensymbolmenü vorhanden. Es sieht so aus:
// Override only if 'Dispose(bool disposing)' has code to free unmanaged resources
~Foo() {
// Do not change this code.
Dispose(calledByFinalizer: true);
}

public void Dispose() {
// Do not change this code.
Dispose(calledByFinalizer: false);
GC.SuppressFinalize(this);
}

// Put cleanup code here
protected virtual void Dispose(bool calledByFinalizer) {
if (_disposed) return;

if (!calledByFinalizer) { /* dispose managed objects */ }

/* free unmanaged resources and set large fields to null */

_disposed = true;
}

Ich habe den vorgeschlagenen Code ein wenig umgestaltet (weil Dispose(bool disposing) jemandem das Gehirn brechen kann und verschachtelte ifs jemandem die Augen brechen können).
Aber mir gehen noch einige Fragen durch den Kopf:
  • Es wird davon ausgegangen, dass die Methode einmal aufgerufen wird. Warum wird dann _disposed = true am Ende der Methode platziert und nicht am Anfang? Wenn IDisposable.Dispose() von verschiedenen Threads aufgerufen wird, können alle die if (_disposed) return;-Prüfung umgehen und den Methodenkörper tatsächlich zweimal ausführen. Warum machen Sie es nicht so:
if (_disposed) return;
else _disposed = true;
  • Warum wird protected virtual void Dispose(bool disposing) als virtuell gekennzeichnet? Jede abgeleitete Klasse hat keinen Zugriff auf das Feld _disposed und kann leicht ihr Verhalten unterbrechen. Wir können nur den optionalen Teil als virtuell markieren, in dem die abgeleitete Klasse alles tun kann, ohne base.Dispose() aufzurufen:
~Foo() => FreeUnmanagedResources();

public void Dispose() {
if (_disposed) return;
else _disposed = true;

DisposeManagedObjects();
FreeUnmanagedResources();

GC.SuppressFinalize(this);
}

protected virtual void DisposeManagedObjects() { }
protected virtual void FreeUnmanagedResources() { }

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post