代码之家  ›  专栏  ›  技术社区  ›  H2ONaCl

取消对“include.NET垃圾回收”的引用有什么好处吗?

  •  8
  • H2ONaCl  · 技术社区  · 14 年前

    假设有以下代码:

    foreach (...)
    {
        List<int> localList = new List<int>(100);
    
        // do stuff
    
        localList = null;
    }
    

    有时,我会在过程即将退出(即返回)时尝试空引用,或者在本例中,在过程即将循环时尝试空引用。这样做有什么好处,哪怕是很小的好处?

    8 回复  |  直到 14 年前
        1
  •  12
  •   JaredPar    14 年前

    对局部变量这样做没有好处。CLR通过JIT确切地知道局部变量何时不再在方法中使用,因此是可收集的。

    Raymond Chen最近在博客上发表了一篇非常深入的文章,讨论了什么时候可以收藏物品。它详细介绍了这个场景,值得一读

        2
  •  4
  •   Mark    14 年前

    不,事实上,在某些情况下,“空化”局部变量可以防止垃圾收集。在正常操作中,一旦变量不再可以从任何正在执行的代码中访问,它就可以用于垃圾回收。如果在方法的末尾,您“清空”了变量,那么您会将它保持为“活动”状态,直到那一刻,并且实际上会延迟它对垃圾回收的可用性。

        3
  •  2
  •   Pat    14 年前

        4
  •  2
  •   Stephen Cleary    14 年前

    我写道 a long and exhaustive blog article answering this question .

    • 实例字段几乎不需要设置为null。只有一个例外:如果引用对象的寿命比被引用对象的寿命长,则实例字段可能设置为null。[请注意,在 IDisposable.Dispose 不符合此测试,不应鼓励]。

        5
  •  2
  •   supercat    14 年前

    如果类有终结器,任何非空的对象引用字段都会导致引用的对象被保留的时间比其他情况下长。如果在finalizer运行之前就知道对象是不必要的,那么清除对象引用字段将允许对象比其他情况下更快地被收集一代。这可能是一个巨大的胜利。

    如果一个对象的生存期(有用或不有用)预计要比它有引用的对象的有效生存期长,那么不必要地保留引用将阻止后一个对象被收集,直到前一个对象被收集为止(即引用将强制后一个对象被保留,即使它已经变得无用)。清除引用将避免该问题。

        6
  •  1
  •   Kent Boogaart    14 年前

        7
  •  0
  •   Jon Hanna    14 年前

    有一个很重要的情况是空值会产生影响,那就是当您使用一个调试构建时,某些jit优化被关闭。当对象被清理时,许多更有趣的行为可以停止,以使调试更容易。

    这一点很重要,因为它可能会导致错误地理解发布版本中正在发生的事情。

        8
  •  0
  •   xanatos    13 年前

    过早优化 (对许多人来说是万恶之源),所以除非你真的需要记忆,否则你不应该这么做。

    • 您知道的对象的属性将不再被引用(例如,您在私有属性中缓存了一些复杂的计算)。你知道你不再需要它了,你把它擦干净)但这一次是很多人说的

    • 复杂方法中的字段。这一点与其他人所说的相反,但我有一个例子,所以我知道我是对的:-)现在,通常,在 序贯法

    但我说过 序贯法 例如,因为mono的GC与.NET的GC不同)。

    释放 模式和启动 (so CTRL-F5)并观察结果:

    using System;
    
    namespace ConsoleApplication17
    {
        class Program
        {
            static void Main()
            {
                const int cycles = 1000000;
    
                {
                    string str = new string(' ', 10000000);
    
                    Console.WriteLine("Let's see when the GC will free the memory");
                    Console.WriteLine("Start: {0}", GC.GetTotalMemory(true));
    
                    for (int i = 0; i < 1000000; i++)
                    {
                        if (i == cycles - 1)
                        {
                            Console.WriteLine("Near end: {0}", GC.GetTotalMemory(true));
                        }
    
                        //Here we reference the string, 
                        //but only in the first 100 iterations
                        if (i < 100 && str[str.Length - 1] == 'c')
                        {
                            throw new Exception();
                        }
                    }
    
                    Console.WriteLine("End: {0}", GC.GetTotalMemory(true));
                }
    
                Console.WriteLine();
    
                {
                    string str = new string(' ', 10000000);
    
                    Console.WriteLine("Let's do the work for him");
                    Console.WriteLine("Start: {0}", GC.GetTotalMemory(true));
    
                    for (int i = 0; i < 1000000; i++)
                    {
                        if (i == cycles - 1)
                        {
                            Console.WriteLine("Near end: {0}", GC.GetTotalMemory(true));
                        }
    
                        //Here we reference the string, 
                        //but only in the first 100 iterations
                        if (i < 100 && str[str.Length - 1] == 'c')
                        {
                            throw new Exception();
                        }
                        else if (i == 100)
                        {
                            str = null;
                            Console.WriteLine("Just nullified the string: {0}", GC.GetTotalMemory(true));
                        }
                    }
    
                    Console.WriteLine("End: {0}", GC.GetTotalMemory(true));
                }
    
                Console.ReadKey();
            }
        }
    }
    

    结果是:

    Let's see when the GC will free the memory
    Start: 20042264
    Near end: 20042888
    End: 42872
    
    Let's do the work for him
    Start: 20042888
    Just nullified the string: 42872
    Near end: 42872
    End: 42872
    

    for

    但是记住这些话 过早优化