c# 析构函数(和终结器?)在我的程序结束时自动调用 - 我应该做些什么吗?

c# destructors (or finalisers?) called automatically at the end of my program - should I do somthing about that?

所以我一直在阅读大量关于如何处理内存分配和终结器等的帖子......我想我很清楚,直到我看到我从 运行 我的程序中获得的调试.该程序本身位于安全网络上,我的 "internet access" PC 没有 C#,因此下面未经测试的示例可能不会给出完全相同的行为,但希望能够展示我所看到的:

我有两个文件:

cli.cs

for (int i = 1; i <= 3; i++)
{
    Console.WriteLine("------ ITERATION " + i + "------");
    Regression.Tests.FileOperations.runTest();
}
Console.WriteLine("Test Finished");

FileOperations.cs

class FileOperations
{
    Obj1 obj1 = null;
    Obj2 obj2 = null;

    public void doStuff()
    {
        // Clear the objects
        obj1 = null;
        obj2 = null;

        // Create the objects
        obj1 = new Obj1();
        obj2 = new Obj2();

        // do stuff (in this case just sleep for 5 seconds)
        Thread.Sleep(5000);
    }

    // Static function so its can be called without instance
    static public void runTest()
    {
        FileOperations fileOps = new FileOperations();
        fileOps.doStuff();
    }
}

所以我对此进行了测试,似乎一切正常。但是我程序的输出给了我这个调试:

------ ITERATION 1 ------
------ ITERATION 2 ------
------ ITERATION 3 ------
Test Finished
~Obj1()
~Obj2()
~Obj1()
~Obj2()
~Obj1()
~Obj2()

所以,如果我正确地清除了对象(我可能不是?)为什么我的所有 Obj1 和 Obj2 都只在程序结束时被删除? - 也许这是正确的? - 我还没有找到任何具有相同输出的人的例子...

您只有 3 次迭代,因此在您的程序中没有很多时间点可能会发生垃圾回收。因此,即使 GC 会启动 三次 (我在这个小场景中对此表示怀疑),您也无法确定这种情况是否发生在 之前 下一次迭代或只是 所有这些之后。 GarbageCollection 的过程非常复杂,尤其是不确定的,因此您无法确定 确切地 何时从内存中释放实例。

虽然您有三个不同的 FileOperations 实例,它们拥有自己的 Obj1Obj2 实例,但这些实例可能会或可能不会保留在堆中,直到 GC 最终决定开始。这至少会在您的应用程序终止时发生,但通常会更早。您 可以 对 GC 的唯一期望是它 将 运行。 GC 在另一端工作的 最频繁 点是当实例超出范围并且不再存在对该实例的引用时。在您的情况下,这是您的代码中不再使用 FileOperations 的实例的时候。

所以在你的场景中你有或多或少的两个选择:

  1. GC 在每次迭代或至少 一些 迭代中工作,至少比你的应用程序终止早得多
  2. 当您的应用终止时

由于您的程序非常小,因此出现第二种选择的可能性非常高。顺便说一句,这提高了整体性能,因为 GC 不需要一直工作 - 或者特别是释放任何实例 - 只需要几次(或者在你的情况下可能是一次)。

GC 做你的清理不使用终结器你可以使用终结器当你想为你的 class 实现一次性模式并覆盖处置方法我在我的 github 回购中做到了 https://github.com/garapricot/MVCBookStore/blob/master/DAL/Services/BookService.cs