如果编译了Conditional方法,则在编译时仍会对每个调用的参数进行类型检查。这是什么动机?例如:
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int x = 2;
string st = "";
// this invocation compiles fine
ConditionalMethod(x, st);
// this invocation won't compile
ConditionalMethod(st, x);
}
[Conditional("condition")]
public static void ConditionalMethod(int x, string st) { }
}
}
为清楚起见,条件符号“condition”未在此上下文中定义,因此从编译产生的MSIL中省略了方法调用。这与定义的here规范相同,所以没有惊喜。想象一个更复杂的场景:
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ConditionalMethod(new Bar());
}
[Conditional("condition")]
public static void ConditionalMethod(Foo foo) { }
public class Foo { }
#if condition
public class Bar : Foo { }
#else
public class Bar { }
#endif
}
}
'ConditionalMethod'的调用仅在定义条件符号“condition”时才包含在结果编译中。然而,在那种情况下,Bar CAN实际上是向Foo倾斜。如果编译器知道对'ConditionalMethod'的调用将被编译掉,那么它是否也应该意识到如果我们关心这个方法的调用,这个代码将是合法的?是的,这是一个人为的,分裂的例子,但它有助于说明我的问题。我要求出于良性的好奇心,因为这已经让我感到厌倦了很长一段时间。请帮忙,Jon Skeet。 :)
答案 0 :(得分:2)
想象一下这段代码
class Program
{
static void Main(string[] args)
{
int x = 2;
string st = "";
// this invocation compiles fine
Blah(x, st);
// this invocation won't compile
Blah(st, x);
}
[Conditional("condition")]
public static void Blah(int x, string st) { }
public static void Blah (string st, int x, int y) { }
public static void Blahh(string st, int x) { }
}
方法的签名是将调用与应该调用的方法相关联的关键部分。必须在知道条件属性是否适用之前进行该关联。在上面的示例中,调用与任何方法都不匹配。编译器必须做出一个信念的飞跃,猜测你意味着 Blah(int,string)。但这是猜测,因为签名不匹配(参数类型的顺序错误)。 Blah(string,int,int)也非常接近 - 你只是忘了一个论点。 Blahh(string,int)也很接近 - 你只是在名字中输入了一个拼写错误。
有关类似示例,请参阅this blog post by Eric Lippert(谁知道这些内容)。
因此参数必须在调用时明确定义, 即使呼叫将被删除。实际上,电话不可能 除非论证存在,否则将其删除!
以后
条件编译指令的效果发生在 lex 时间; 删除的#if块中的任何内容都被词法分析器视为 一条评论。这就像你只是删除了整个内容 阻止并用空格替换它。但删除呼叫网站 取决于条件属性发生在语义分析时间; 执行语义分析所必需的一切必须是 本强>