C# 类析构函数中使用 new() 的效果

Sek*_*har 0 c#

作为一项学术练习,尝试确定导致程序退出的原因 - 这不是 StackOverFlowException,而是常规终止。我所做的就是在类的析构函数/终结器上创建一个新实例。我期待这段代码像循环一样永远运行while(true)

class Animal
{
    static int i = 0;
    public Animal()
    {
        Animal.i = Animal.i + 1;
        Console.WriteLine(i + " Object created.." );
    }

    ~Animal()
    {
        new Animal();
    }

}
internal class Program
{
    static void Main(string[] args)
    {
        Animal a = new Animal();
    }

}
Run Code Online (Sandbox Code Playgroud)

运行 1 输出:

76727 Object created..
76728 Object created..
76729 Object created..
Press any key to continue . . .
Run Code Online (Sandbox Code Playgroud)

运行 2 输出

76818 Object created..
76819 Object created..
76820 Object created..
76821 Object created..
Press any key to continue . . .
Run Code Online (Sandbox Code Playgroud)

JLR*_*she 7

垃圾收集器控制何时调用终结器,并且根本不能保证终结器将被调用。程序可能会因尚未调用终结器的对象而终止。在您的情况下,程序很可能会到达一个点,无论 GC 中还剩下什么,程序都会终止,并停止调用任何终结器。

文档中:

笔记

终结器是否作为应用程序终止的一部分运行特定于 .NET 的每个实现。当应用程序终止时,.NET Framework 会尽一切合理努力为尚未进行垃圾收集的对象调用终结器,除非此类清理已被抑制(GC.SuppressFinalize例如,通过调用库方法)。.NET 5(包括 .NET Core)和更高版本不会调用终结器作为应用程序终止的一部分。有关更多信息,请参阅 GitHub 问题 dotnet/csharpstandard #291。

如果您需要在应用程序退出时可靠地执行清理,请为该System.AppDomain.ProcessExit事件注册一个处理程序。该处理程序将确保在应用程序退出之前为所有需要清理的对象调用IDisposable.Dispose()(或, )。IAsyncDisposable.DisposeAsync()因为不能直接调用 Finalize,并且不能保证垃圾收集器在退出前调用所有终结器,所以必须使用DisposeDisposeAsync来确保释放资源。