Ich versuche zu lernen, wie Finalisierung und Destruktor in C # funktioniert. Ich habe versucht, den Code im System.Object.Finalize
Beispiel (Code kopiert-eingefügt, keine Änderungen vorgenommen), aber die Ausgabe ist nicht die gleiche wie erwartet, es zeigt, dass der Destruktor nie aufgerufen wird.
Der Code lautet:
%Vor%Aktualisierung:
Wenn ich Visual Studio und .NET Framework 4.5 verwende, funktioniert der Code wie erwartet: Ausgabe wie Beispiel:
%Vor%Wenn ich die dotnet core-App verwende, funktioniert der Code nicht: Die tatsächliche Ausgabe ist:
%Vor%Warum ist das in .NET Core anders?
Informationen aus Kommentaren von Peter Duniho und Henk Holterman zusammenführen und weiter ausbauen:
Dieses Verhalten verstößt gegen die C # 5.0-Spezifikation und die aktuelle Version Entwurf der Spezifikation C # 6.0 von Microsoft , die besagt:
Vor dem Beenden einer Anwendung werden Destruktoren für alle Objekte aufgerufen, die noch nicht als Garbage Collected erfasst wurden, sofern diese Bereinigung nicht unterdrückt wurde (z. B. durch Aufruf der Bibliotheksmethode
GC.SuppressFinalize
).
Aber es ist kein Fehler, .Net Core weicht absichtlich vom .Net-Framework-Verhalten ab, wie in einem corefx-Problem
Derzeit wird ein Best-Effort-Versuch unternommen, Finalizer für alle finalisierbaren Objekte während des Herunterfahrens auszuführen, einschließlich erreichbarer Objekte. Das Ausführen von Finalizern für erreichbare Objekte ist nicht zuverlässig, da sich die Objekte in einem nicht definierten Status befinden.
...
Vorschlag
Führen Sie die Finalizer beim Herunterfahren nicht aus (für erreichbare oder nicht erreichbare Objekte)
...
Unter diesem Vorschlag wird nicht garantiert, dass alle fertigstellbaren Objekte vor dem Herunterfahren finalisiert werden.
Vermutlich aufgrund dessen ist der aktuelle Entwurf der Spezifikation C # 5.0 von ECMA > Diese Anforderung wurde abgeschwächt, sodass .Net Core nicht gegen diese Version der Spezifikation verstößt:
Vor dem Beenden einer Anwendung sollte eine Implementierung alle angemessenen Anstrengungen unternehmen, um Finalizer (§ 16.13) für alle ihre Objekte aufzurufen, die noch nicht bereinigt wurden, sofern diese Bereinigung nicht unterdrückt wurde (durch einen Aufruf der Bibliotheksmethode)
GC.SuppressFinalize
, zum Beispiel). Die Implementierung sollte alle Bedingungen dokumentieren, unter denen dieses Verhalten nicht garantiert werden kann.
Die Fertigstellung erfolgt erst, wenn der Garbage Collector ausgeführt wird. Die Garbage-Collection wird nur ausgeführt, wenn dies erforderlich ist (z. B. wenn der Arbeitsspeicher knapp ist) oder wenn Sie zwingt es zum Ausführen .
Versuchen Sie,
hinzuzufügen %Vor%zu Ihrem Code und sehen, ob der Finalizer in dieser Situation ausgeführt wird.
Tags und Links .net c# .net-core destructor