c# - Finalizer 没有被一次性类型对象调用

标签 c# .net memory-leaks garbage-collection

重现步骤:

这是我的代码:

    using (TestClass test = new TestClass())
    {

    }

    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();

这就是我定义 TestClass 的方式:

public class TestClass : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
        //GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            Console.WriteLine("Disposing TestClass.");
        }
    }

    ~TestClass()
    {
        Dispose(false);
        Console.WriteLine("TestClass Finalizer called");
    }
}

预期行为: 我确实看到“Disposing TestClass”按预期在 using 语句后打印,但我也希望在我运行 GC 命令后打印“TestClass Finalizer called”。我确保我跳过调用 GC.SuppressFinalize(this);在 Dispose 方法中。看起来已处置的变量即使在超出范围后也不会最终确定。它们似乎在程序退出前就完成了。

实际行为: 我只看到在 using 语句之后打印了“Disposing TestClass”,正如预期的那样,在 GC 命令之后没有看到“TestClass Finalizer called”。我只是在程序退出前才看到它。

这不是内存泄漏吗?

如果我将其转换为非一次性类并像下面这样更新代码,我确实会看到在 GC 命令之后调用终结器。

TestClass test = new TestClass();
test = null;

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();


public class TestClass
{
    ~TestClass()
    {   
        Console.WriteLine("TestClass Finalizer called");
    }
}

最佳答案

根据微软对 Object.Finalize Method () 的描述

The exact time when the finalizer executes is undefined. To ensure deterministic release of resources for instances of your class, implement a Close method or provide a IDisposable.Dispose implementation.

将终结器视为第二道防线。如果程序未能调用 CloseDispose,则终结器将进行更改以纠正遗漏。

这仍将确保文件将在程序退出时关闭,例如,除非另一个终结器未退出并因此阻塞其他终结器,或者如果灾难性异常正在粗暴地终止程序。

这不是内存泄漏。如果内存变得稀缺,垃圾收集器 (GC) 可以在程序退出之前很久就决定释放资源并调用终结器。

关于c# - Finalizer 没有被一次性类型对象调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42329589/

相关文章:

c# - 如果未安装 SQL Server 2005,我能否创建并连接到 SQL Server CE 数据库?

ios - ffmpeg中的内存泄漏

c# - 将 doc 文件插入 SQL Server 中的列

c# - 用于通用方法的 Microsoft Fakes shim

C# 客户端 - Perl 服务器 - 文件路径区分大小写

c# - 连续的 LINQ 查询

android - 完成 Activity 后内存泄漏

c# - .Net 内存增长问题

c# - DBMigrator 无法首先读取 ef6 代码中的访问 token - SQL 连接

java - 如何构建反向按位运算