2009-04-16 1 views
2

Я запускаю приведенный ниже код, и результат полностью отличается, когда он запускается в режиме Release. В режиме Debug он никогда не собирает объект класса A и в режиме Reaelse, он сразу же собирает объект класса A.GC.COllect(), похоже, не работает в режиме отладки

Может кто-нибудь объяснить, почему.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication2 { 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      A obj = new A(); 

      B bobj = obj.objB; 

      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 

      while (bobj.isLive) 
      { 
       Console.WriteLine("Is Alive!!"); 
      } 

      Console.WriteLine("Is Dead!!"); 

      Console.ReadLine(); 
     } 
    } 

    class A:IDisposable 

    { 
     public B objB = new B(); 

     public A() 
     { } 

     ~A() 
     { 
      objB.Dispose(); 
     } 

     #region IDisposable Members 

     public void Dispose() 
     { 
      GC.SuppressFinalize(this); 
     } 

     #endregion 


    } 
    class B:IDisposable 
    { 
     public bool isLive = true; 

     #region IDisposable Members 

     public void Dispose() 
     { 
      this.isLive = false; 
      GC.SuppressFinalize(this); 
     } 

     #endregion 
    } } 

ответ

4

В режиме отладки компилятор не оптимизирует локальные переменные. Поэтому ссылка на A все еще существует. В режиме Release компилятор оптимизировал использование, чтобы ссылка была выброшена и объект можно было собрать.

+0

Это не причина. Ссылка не выбрасывается, она считается неактивной, и это не имеет ничего общего с оптимизацией. Это наоборот; переменная может быть оптимизирована от этой точки, поскольку она неактивна. – Guffa

+0

«Брошенный» может быть слишком простым, как объяснение, согласился. Тем не менее, причина верна; в режиме освобождения нет сильной ссылки, которая мешает GC собирать экземпляр. – Lucero

+0

Из-за оптимизаций в режиме выпуска эталонная область действительна только до последнего использования, а не всего блока кода, в котором она определена. Что происходит в режиме отладки, четко указано Лусеро выше. – MSIL

2

Сборщик мусора обрабатывает переменное использование по-разному в режиме отладки и режиме выпуска.

В режиме освобождения использование переменной только там, где она фактически используется. После последнего использования varaible объект предназначен для сбора мусора.

В режиме отладки использование varaible расширено до его объема. Причина этого в том, что окно просмотра в отладчике может отображать значение переменных во всей области.

3

Я просто нашел это поведение в своих тестах. Вставка

obj = null; 

прямо перед тем, как GC.Collect() должен помочь. Я думаю, что это своего рода «имитированная» оптимизация.

+0

Обратите внимание, что это не будет работать, если есть предложение try-catch после вызова GC.Collect. Лучшим решением было бы создать объект в другом методе, чтобы ссылка была вне области действия при запуске GC. – Shocked