C# 析构函数未按预期工作

标签 c# garbage-collection destructor

请看下面的代码。我希望它打印 10,因为我已经显式调用了垃圾收集器。但我总是得到 0 或 20 作为输出。这是为什么?

void Main()
{
    Panda[] forest_panda = new Panda[10];
    for(int i=0; i<forest_panda.GetLength(0);i++)
    {
        forest_panda[i]=new Panda("P1");
    }

    for(int i=0; i<forest_panda.GetLength(0);i++)
    {
        forest_panda[i]=new Panda("P1");
    }

    System.GC.Collect();

    Console.WriteLine("Total Pandas created is {0}",Panda.population);          
}

class Panda
{
    public static int population=0;
    public string name;

    public Panda(string name)
    {
        this.name = name;
        population = population + 1;
    }

    ~Panda()
    {
        population = population - 1;
    }   
}

请注意,Main 的类是由 LINQPad(《C# 4.0 in a Nutshell》一书附带的编辑器)自动创建的。我是 C# 新手。

最佳答案

您还没有运行明确的垃圾回收。来自 GC.Collect() 的文档:

Use this method to attempt to reclaim all memory that is inaccessible. However, the Collect method does not guarantee that all inaccessible memory is reclaimed.

All objects, regardless of how long they have been in memory, are considered for collection; however, objects that are referenced in managed code are not collected. Use this method to force the system to attempt to reclaim the maximum amount of available memory.

垃圾收集器经过高度优化,并在实际进行垃圾收集时由他自己“决定”,然后调用终结器。此外,这一切都是异步完成的。这也是终结器被称为非确定性清理的原因。当清理发生时,你永远不会。

您现在有两个选择。您可以调用 GC.WaitForPendingFinalizers()这将暂停当前线程,直到所有可终结对象都已完成。或者调用这个新的重载:System.GC.Collect(int generation, System.GCCollectionMode mode)GCCollectionMode.Forced 是在 .NET 3.5 中引入的。

请记住,通常没有必要,更重要的是:一个坏主意手动调用垃圾收集器。此外,只有在极少数情况下才需要实现终结器。调用垃圾收集器会减慢运行时间。实现终结器会额外减慢运行时间。垃圾收集器在准备好进行垃圾收集时将所有实现终结器的对象放入终结队列。处理这个队列是昂贵的。 更糟糕的是,当运行终结器时,不能保证您尝试访问的成员仍然存在。很有可能它们已经被抢走了。这就是为什么只有当您有需要清理的非托管资源时才应使用终结器。

您的示例中绝对不需要所有这些。你真正想要的是IDisposable用于确定性清理。

关于C# 析构函数未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3499574/

相关文章:

c# - 自动登录office 365 outlook

c# - 读取 XML 时出错

c# - 使用两个泛型类型参数推断泛型类型

java - 在 Android 上,垃圾收集是按进程还是系统范围进行的?

c++ - 当一个类中有虚函数时,隐式生成的析构函数是否也是虚函数?

c# - 当单击 visual studio 2015 Resharper 上的运行按钮时,我的代码发生了变化

Java 11 - 如何覆盖 JVM 和系统内存中的敏感信息(也许使用 System.gc()?)

java - 在开始时管理 JVM OldGen 峰值

c++ - 如何将析构函数专门用于一种情况或某些情况?

C++ 如何在数组中存储对象而不删除它们