当最后一个条件调用有条件时,为什么C#编译器会删除方法调用链?
考虑以下类别: 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"); } } 现在,如果我们以这种方式调用方法: var a = new A(); var b = a.GetB(); b.Hello(); 在发布版本中(即,无DEBUG标志),我们只会看到GetB控制台上打印的内容,因为Hello()编译器会省略对的调用。在调试版本中,两个打印都会出现。 现在让我们链接方法调用: a.GetB().Hello(); 调试版本中的行为不变。但是,如果未设置标志,则会得到不同的结果:两个调用都被省略,并且控制台上没有打印内容。快速浏览一下IL会发现整个行没有被编译。 根据针对C#的最新ECMA标准(ECMA-334,即C#5.0),Conditional属性置于方法上如下(强调我的意思): 如果在调用点定义了一个或多个与其相关的条件编译符号,则包括对条件方法的调用,否则将省略该调用。(第22.5.3节) 这似乎并不表示应忽略整个链条,因此是我的问题。话虽如此,Microsoft的C#6.0规范草案提供了更多细节: 如果定义了该符号,则包括该呼叫;否则,将忽略该呼叫(包括对接收方的评估和该呼叫的参数)。 没有对调用的参数进行评估的事实有据可查,因为这是人们#if在功能体内使用此功能而不是使用伪指令的原因之一。但是,有关“接收者评估”的部分是新的-我似乎无法在其他地方找到它,并且确实可以解释上述行为。 有鉴于此,我的问题是:在这种情况下,C#编译器不进行评估的原理 是什么a.GetB() ?根据条件调用的接收者是否存储在临时变量中,它的行为是否真的有所不同?