title: Why does the C# compiler remove a chain of method calls when the last one is conditional?
body: <p>Consider the following classes:</p>
  
  <pre><code>public class A {
      public B GetB() {
          Console.WriteLine("GetB");
          return new B();
      }
  }
  
  public class B {
      [System.Diagnostics.Conditional("DEBUG")]
      public void Hello() {
          Console.WriteLine("Hello");
      }
  }
  </code></pre>
  
  <p>Now, if we were to call the methods this way:</p>
  
  <pre><code>var a = new A();
  var b = a.GetB();
  b.Hello();
  </code></pre>
  
  <p>In a release build (i.e. no <code>DEBUG</code> flag), we would only see <code>GetB</code> printed on the console, as the call to <code>Hello()</code> would be omitted by the compiler. In a debug build, both prints would appear.</p>
  
  <p>Now let's chain the method calls:</p>
  
  <pre><code>a.GetB().Hello();
  </code></pre>
  
  <p>The behavior in a debug build is unchanged; however, we get a different result if the flag isn't set: <strong>both</strong> calls are omitted and no prints appear on the console. A quick look at IL shows that the whole line wasn't compiled.</p>
  
  <p>According to the <a href="https://www.ecma-international.org/publications/standards/Ecma-334.htm" rel="noreferrer">latest ECMA standard for C#</a> (ECMA-334, i.e. C# 5.0), the expected behavior when the <code>Conditional</code> attribute is placed on the method is the following (emphasis mine):</p>
  
  <blockquote>
    <p>A call to a conditional method is included if one or more of its associated conditional compilation symbols is
    defined at the point of call, otherwise <strong>the call is omitted</strong>. (§22.5.3)</p>
  </blockquote>
  
  <p>This doesn't seem to indicate that the entire chain should be ignored, hence my question. That being said, the <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/attributes#reserved-attributes" rel="noreferrer">C# 6.0 draft spec from Microsoft</a> offers a bit more detail:</p>
  
  <blockquote>
    <p>If the symbol is defined, the call is included; otherwise, the call (including evaluation of the receiver and parameters of the call) is omitted.</p>
  </blockquote>
  
  <p>The fact that parameters of the call aren't evaluated is well-documented since it's one of the reasons people use this feature rather than <code>#if</code> directives in the function body. The part about "evaluation of the receiver", however, is new - I can't seem to find it elsewhere, and it does seem to explain the above behavior.</p>
  
  <p>In light of this, my question is: <em>what's the rationale behind the C# compiler not evaluating</em> <code>a.GetB()</code> <em>in this situation?</em> Should it really behave differently based on whether the receiver of the conditional call is stored in a temporary variable or not?</p>