C#析构函数无法正常工作

问题描述 投票:5回答:8

请参见下面的代码。我希望它可以打印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(《 Cut 4.0 in a Nutshell》一书附带的编辑器)自动创建的。我是C#的新手。

c# garbage-collection destructor
8个回答
7
投票

您尚未运行显式垃圾回收。从GC.Collect()的文档中:

使用此方法尝试回收所有无法访问的内存。但是,Collect方法不确保所有不可访问的内存被回收。

所有对象,无论多长时间他们一直在记忆中,考虑收集;然而,托管中引用的对象代码未收集。用这个强制系统尝试的方法回收最大数量的可用内存。

垃圾收集器经过高度优化,当他实际进行垃圾收集然后调用终结器时,将由他自己“决定”。另外,所有这些都是异步完成的。这就是为什么将终结器称为非确定性清理的原因。当您进行清理时,您现在再也不会。

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

请记住,通常没有必要,更重要的是:一个坏主意手动调用垃圾收集器。此外,仅在极少数情况下才需要实现终结器。调用垃圾收集器会减慢运行时间。实现终结器将另外减慢运行时间。当垃圾回收器准备好进行垃圾回收时,垃圾回收器会将实现该终结器的所有对象放入终结队列中。处理此队列非常昂贵。更糟糕的是,运行终结器时,不能保证您尝试访问的成员仍然存在。他们很有可能已经被劫持收集了。这就是为什么仅当您有需要清理的[[unmanaged资源时才应使用终结器的原因。在您的示例中,绝对不需要所有这些。您强烈想要的是IDisposable以进行确定性清除。


6
投票
[这里有几件事要注意:

3
投票
尝试在垃圾回收后添加System.GC.WaitForPendingFinalizers。http://www.developer.com/net/csharp/article.php/3343191/C-Tip-Forcing-Garbage-Collection-in-NET.htm

2
投票
您创建了二十个对象,因此该值将为20。显式调用System.GC.Collect()实际上并不能保证调用析构函数。因此,如果调用它,那么所有20个对象都可能被破坏,或者可能没有一个对象被破坏。

1
投票
在.NET中,对象生存期为non-deterministic,并且行为与C ++构造函数/析构函数所期望的不同。实际上,.NET对象在技术上没有析构函数。终结器的不同之处在于,它需要在对象的生存期内清除对象使用的

unmanaged


1
投票
使用析构函数(也称为终结器)并不是在C#中做事的好方法。即使您显式调用垃圾回收器,也无法保证终结器会运行。您也不应尝试强制进行垃圾回收,因为这可能会对应用程序的整体性能产生负面影响。

1
投票
The

Dispose Pattern


0
投票
它在发布版本中为我调用。但是在调试中的行为有所不同。
© www.soinside.com 2019 - 2024. All rights reserved.