c#destructors(或者终结者?)在我的程序结束时自动调用 - 我应该对此做些什么吗?

时间:2017-09-26 08:02:02

标签: c# garbage-collection finalizer

所以我一直在阅读大量有关如何处理内存分配和终结器的帖子......我想我很清楚,直到我看到运行程序时得到的调试。该计划本身是在一个安全的网络和我的互联网接入" 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();
    }
}
  • 所以在cli.cs中我们在循环中调用静态函数runTest() 迭代3次。
  • runTest()实例化FileOperations对象和 然后调用它的doStuff()函数。
  • doStuff()通过将它们设置为null来清除所有先前的对象(我读过这是这样做的方法)。然后它创建对象的新实例以供使用。

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

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

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

3 个答案:

答案 0 :(得分:3)

您只有三次迭代,因此当您进行Garabage-Collection时,程序中的时间点可能不多。因此,即使GC将三次(我怀疑在这个小场景中)你无法确定在下一次迭代之前是还是之后 / em>所有这些。 GarbageCollection的过程非常复杂,并且特别是不确定的,因此您无法确定完全何时从内存中释放实例。

虽然你有三个不同的FileOperations实例,它们拥有自己的Obj1Obj2实例,但这些实例可能会也可能不会保留在堆上,直到GC最终决定启动这至少在您的应用程序终止时发生,但通常要早得多。 GC在另一端工作的最简单的点是当一个实例超出范围并且不再存在对该实例的引用时。在您的情况下,这是在代码中不再使用FileOperations的实例时。

因此,您的方案中有两个或多或少的选项:

  1. GC处理每次迭代或至少部分,至少在您的应用程序终止之前很久
  2. 当您的应用终止时
  3. 由于您的计划很少,所以第二种选择的可能性非常高。顺便说一句,这可以提高整体性能,因为GC不需要一直工作 - 或者特别是免费任何实例 - 所有时间,只有少数(或者在你的情况下可能是一个)时间。

答案 1 :(得分:-1)

  

如果您不使用任何析构函数,则无需在C#中使用析构函数   非托管资源。因为所有托管资源都是垃圾   当对象不在时,CLR会自动完成收集   使用..所以你不需要在托管的情况下实现析构函数   资源。

答案 2 :(得分:-1)

GC你做清理不使用终结器你可以使用终结器当你想要实现idisposable模式到你的类和覆盖dispose方法我在我的github repo这里做了它 https://github.com/garapricot/MVCBookStore/blob/master/DAL/Services/BookService.cs