title: How does C# compiler remove Debug.Assert's in release builds?
body: <p>I was recently going through some code and considering whether I need to be careful with the expressions placed inside <code>Debug.Assert</code> statements, such as expensive operations or those with side effects.  However, it appears the compiler is pretty smart about completely removing the <code>Assert</code> statement and inner expressions.</p>
  
  <p>For example, the following will only print on debug builds:</p>
  
  <pre><code>static void Main(string[] args)
  {
      Debug.Assert(SideEffect());
  }
  private static bool SideEffect()
  {
      Console.WriteLine("Side effect!");
      return true;
  }
  </code></pre>
  
  <p>And this will complain that <code>o</code> is being used before initialization on release builds:</p>
  
  <pre><code>static void Main(string[] args)
  {
      object o;
      Debug.Assert(Initialize(out o));
      o.ToString();
  }
  private static bool Initialize(out object o)
  {
      o = new object();
      return true;
  }
  </code></pre>
  
  <p>It even seems to stand up to expressions such as this (printing "After" in both cases):</p>
  
  <pre><code>static void Main(string[] args)
  {
      if (false) Debug.Assert(true);
      Console.WriteLine("After");
  }
  </code></pre>
  
  <p>I was a little suprised with how smart the compiler is here and its ability to correctly detect cases when the <code>Debug.Assert</code> is removed.  So, it got me curious..</p>
  
  <ul>
  <li>How exactly is the statement removed?  The expression tree must be built before the statement is removed in order to properly execute the above <code>if</code> statement correctly.</li>
  <li>Is the <code>System.Diagnostics.Debug</code> class special here, or is it possible to build your own methods with similar handling?</li>
  <li>Are there any ways to "trick" the preprocessor here?  Even better, are there situations that one might encounter in real-world code where this could be problematic?</li>
  </ul>