title: Why C# Garbage Collection behavior differs for Release and Debug executables?
body: <p>Let's consider following simple program:</p>
  
  <pre><code>class Program
  {
      class TestClass
      {
          ~TestClass()
          {
              Console.WriteLine("~TestClass()");
          }
      }
  
      static void Main(string[] args)
      {
          WeakReference weakRef;
          {
              var obj = new TestClass();
              weakRef = new WeakReference(obj);
              Console.WriteLine("Leaving the block");
          }
  
          Console.WriteLine("GC.Collect()");
          GC.Collect();
          System.Threading.Thread.Sleep(1000);
          Console.WriteLine("weakRef.IsAlive == {0}", weakRef.IsAlive);
  
          Console.WriteLine("Leaving the program");
      }
  }
  </code></pre>
  
  <p>When built in Release mode, it predictably prints:</p>
  
  <pre><code>Leaving the block
  GC.Collect()
  ~TestClass()
  weakRef.IsAlive == False
  Leaving the program
  </code></pre>
  
  <p>When Debug version is launched (not under the Debugger, usual launch from Windows Explorer), the output differs:</p>
  
  <pre><code>Leaving the block
  GC.Collect()
  weakRef.IsAlive == True
  Leaving the program
  ~TestClass()
  </code></pre>
  
  <p>Running under the debugger for both versions doesn't change the output.</p>
  
  <p>I've discovered this strange difference during debugging of my custom collection that keeps weak references to objects.</p>
  
  <p>Why garbage collector in debug executables does not collect objects that clearly are not referenced?</p>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>Situation differs if object creation is performed in other method:</p>
  
  <pre><code>class Program
  {
      class TestClass
      {
          ~TestClass()
          {
              Console.WriteLine("~TestClass()");
          }
      }
  
      static WeakReference TestFunc()
      {
          var obj = new TestClass();
          WeakReference weakRef = new WeakReference(obj);
          Console.WriteLine("Leaving the block");
  
          return weakRef;
      }
  
      static void Main(string[] args)
      {
          var weakRef = TestFunc();
  
          Console.WriteLine("GC.Collect()");
          GC.Collect();
          System.Threading.Thread.Sleep(1000);
          Console.WriteLine("weakRef.IsAlive == {0}", weakRef.IsAlive);
  
          Console.WriteLine("Leaving the program");
      }
  }
  </code></pre>
  
  <p>It outputs the same output in Release and Debug versions:</p>
  
  <pre><code>Leaving the block
  GC.Collect()
  ~TestClass()
  weakRef.IsAlive == False
  Leaving the program
  </code></pre>