C# 在包含静态字段的非静态类中启动析构函数?

C# 在包含静态字段的非静态类中启动析构函数?,c#,asp.net,asp.net-mvc,C#,Asp.net,Asp.net Mvc,我想测试在类中何时调用析构函数,当它是一个简单的类时,一切都按照预期进行-当我们离开实例的作用域时,析构函数被调用 但当我们添加一个静态字段时,它不会发生。 有人能解释这种情况背后的概念吗 public class Test { ~Test(){} private static string StaticField=""; private float NonStaticField; } 对于其他非静态且具有值的字段,会发生什么情况?他们从不打扫吗 我测试了通过控

我想测试在类中何时调用析构函数,当它是一个简单的类时,一切都按照预期进行-当我们离开实例的作用域时,析构函数被调用

但当我们添加一个静态字段时,它不会发生。 有人能解释这种情况背后的概念吗

public class Test
{
    ~Test(){}
    private static string StaticField="";
    private float NonStaticField;    
}
对于其他非静态且具有值的字段,会发生什么情况?他们从不打扫吗

我测试了通过控制器调用析构函数,如下所示

public class HomeController : Controller
{
    // GET: Home
    public ActionResult Index()
    {
        var ts = new Test();
        return View();
    }
}
当我离开
索引后删除静态字段时,调用析构函数


编辑:调用析构函数有点奇怪,因为它在静态和非静态方法中的行为不同,如果我在静态方法中创建实例并离开作用域,则调用析构函数。

调用析构函数时没有可预测的点。内存由以下程序管理:

当满足下列条件之一时,会发生垃圾回收 正确:

  • 系统的物理内存不足。这是由操作系统发出的内存不足通知或 主持人

  • 托管堆上已分配对象使用的内存超过可接受的阈值。该阈值是连续的 在流程运行时进行调整

  • 调用GC.Collect方法。在几乎所有情况下,您都不必调用此方法,因为垃圾收集器会运行 连续不断地。此方法主要用于特殊情况和 测试

所以通常情况下,当这种情况发生时,你并不感兴趣,只是它发生了。为了亲眼看看,我试着用一个简单的测试程序重复你的实验。创建没有静态字段的测试类的测试函数被多次调用。所有创建的实例只有在程序完成时才最终确定并释放


如果这很重要,并且您希望控制实例完成的时间,那么您应该实现该接口并使用。

我想根据microsoft的文章,终于找到了幕后发生的事情, 垃圾收集器将对象视为三代中的一代, 第0代、第1代、第2代。 它含蓄地说

堆被组织成几代,因此它可以处理长寿命的 短命物体。垃圾收集主要发生在 回收通常只占用一小部分空间的短期对象 堆的一部分

第二代。此生成包含长寿命对象。一个例子 长寿命对象的名称是服务器应用程序中 包含进程期间处于活动状态的静态数据

属于第2代类别的对象不会立即处理, 当然,web应用程序中的垃圾收集器行为不同于windows应用程序。 要确定垃圾收集器何时执行其工作,我们应该了解
latency

延迟是指垃圾收集器侵入您的系统的时间 应用

web应用程序的默认延迟模式为交互式

启用垃圾收集并发并在 应用程序正在运行。这是垃圾的默认模式 在工作站上收集,并且比批处理具有更少的侵入性。信息技术 平衡响应能力和吞吐量。此模式相当于 工作站上并发的垃圾回收

我很确定这是一个需要精确考虑的广泛话题, 您可以使用下面的链接阅读有关垃圾收集的更多信息


你是如何测试没有调用析构函数的?很有趣。如果再次添加对GC.Collect(0)和命中索引页的调用,将收集在第一次命中中创建的对象并执行终结器(析构函数是C++)。这意味着您的测试对象没有以任何方式传播到Gen1。另一方面,我不明白为什么在没有静态字段的情况下执行它?您没有填充整个Gen0来触发GC。我认为是调试器让它这样做的。它在某种程度上与堆栈、堆和内存管理概念有关,但我不知道在.Net中如何处理具有静态成员的类。我没有看到任何错误。你怎么查的?一切都很好-是的,你是对的,你上面提供的所有信息都得到了尊重,但问题是,当类包含静态字段时,我想知道是什么原因导致在离开创建范围后不调用(至少立即调用)析构函数,虽然created instance无法访问静态字段。但我并不担心调用析构函数,事实上,我只是想了解这种情况背后的概念,我很确定它与堆和堆栈内存概念以及它们的管理方式有某种关联。我的观点是,GC基本上做它做的事情,当它做的时候。在您的示例中,它在没有静态成员的情况下立即释放了实例。就我而言,它一直等到节目结束。对于静态成员,内存需要保留,以便以后访问时可以返回相同的值。为了进行测试,您可以尝试用静态成员实例化2个对象,并查看其中一个是否立即被销毁。我不会感到惊讶。