【问题标题】:Would the instance reference parameters passed into the static methods get garbage collected?传递给静态方法的实例引用参数会被垃圾收集吗?
【发布时间】:2010-04-21 12:58:40
【问题描述】:

我知道 .Net 托管世界中的静态对象被加载到永远不会被垃圾回收的加载器堆中。

传递给静态方法的实例引用参数会发生什么。一旦静态函数完全执行,它们是否会被垃圾收集,或者它们将永远存在,因为这些实例引用变量一旦传递给静态方法?

今晚我真的很困惑;请指导我。

感谢和问候

123 开发人员。

【问题讨论】:

    标签: c# .net static


    【解决方案1】:

    是的,它们在静态函数执行后被垃圾回收。您正在非静态上下文中创建对象,因此它们不是在加载程序堆中创建的。只是将引用传递给静态函数并不会改变任何东西。

    【讨论】:

      【解决方案2】:

      您将引用传递给静态方法并不意味着该对象将以任何方式植根,因此仅凭这一点不足以阻止它被收集。

      是否可以在方法调用期间或仅在完成后收集,取决于方法对参数的作用,以及对象是否在方法调用之外使用。

      例如,考虑这个假设的代码:

      public static class Program()
      {
          public static void Main()
          {
              SomeObject o = new SomeObject();
              OtherMethod(o);
          }
      
          private static void OtherMethod(SomeObject x)
          {
              // lots of code here, but none that uses x
          }
      }
      

      在这种情况下,可以在调用OtherMethod 期间收集 o,前提是您编译并运行发布版本。对于发布版本,不再使用的变量和参数,即没有使用它的代码,被认为是死的,因此在检查是否有对对象的实时引用时不再计算在内。

      在 Debug 构建中,所有变量和参数都会人为地保持活动状态,直到方法返回,这样您就可以设置断点并检查变量,即使没有使用它的代码。

      因此,如果您要从调试版本运行上述代码,则该对象将一直保持活动状态,直到 Main 返回。

      【讨论】:

      • +1 非常有趣的附加信息。不知道。我再次吸取的教训:调试和发布版本在底层的行为非常不同,而从外部看却是相同的。
      • 由于每日投票限制,不能给你承诺的投票:(
      • +1 人们一定没有意识到这一点。并且令人难以置信的是,规范中没有任何内容会禁止 CLR 使实例符合 GC 甚至在分配变量 'o' 之前,因为它的成员从未被取消引用。实际上,CLR 可能还没有那么复杂的启发式算法,但理论上是可能的。
      【解决方案3】:

      一旦静态方法处理完变量,它就不再持有对它的引用(如果将它分配给静态变量,那就不同了)。但这并不意味着它会立即被垃圾收集。除非您明确告诉 GC 运行,否则它何时运行取决于运行时认为何时需要释放内存。说实话,这在应用程序的生命周期中可能永远不会发生(资源将随着应用程序的结束而被释放)。然而,这极不可能,尽管在技术上是可行的。

      【讨论】:

      • 正确 - 只要不将实例变量分配给静态字段或将对它的引用存储在一个字段中。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-27
      • 1970-01-01
      • 2014-03-09
      • 1970-01-01
      • 2012-07-19
      • 2015-10-08
      • 1970-01-01
      相关资源
      最近更新 更多