考虑以下类:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我们以这种方式调用方法:
var a = new A();
var b = a.GetB();
b.Hello();
Run Code Online (Sandbox Code Playgroud)
在发布版本中(即没有DEBUG标志),我们只会GetB在控制台上看到打印,因为Hello()编译器会忽略调用.在调试版本中,两个打印都会出现.
现在让我们链接方法调用:
a.GetB().Hello();
Run Code Online (Sandbox Code Playgroud)
调试版本中的行为保持不变; 但是,如果未设置标志,我们会得到不同的结果:两个调用都被省略,并且控制台上没有打印.快速浏览一下IL可以看出整行都没有编译过.
根据C#的最新ECMA标准(ECMA-334,即C#5.0),将Conditional属性放置在方法上时的预期行为如下(强调我的):
如果在呼叫点定义了一个或多个相关的条件编译符号,则包括对条件方法的调用,否则省略该调用.(§22.5.3)
这似乎并不表示整个链应该被忽略,因此我的问题.话虽如此,微软的C#6.0草案规范提供了更多细节:
如果定义了符号,则包括呼叫; 否则,省略呼叫(包括接收机的评估和呼叫的参数).
没有评估调用参数的事实已被充分记录,因为这是人们使用此功能而不是#if函数体中的指令的原因之一.然而,关于"接收器的评估"的部分是新的 - 我似乎无法在其他地方找到它,它似乎解释了上述行为.
鉴于此,我的问题是:在这种情况下,C#编译器没有评估的理由 是什么a.GetB() ? …