实际的调用Main
被转换为 a CallSite
,因为您正在使用 a 调用调用dynamic param
。为在运行时CallSite
调用此方法所需的所有准备工作。但是,问题是,它有一个属性,这意味着它需要在编译时将信息传递给编译器预处理器Assert
Conditional
这篇博文解释:
条件属性可以放在方法(和 whidbey 中的属性)上,以指示编译器在未定义符号时有条件地删除对函数的调用。这对于仅调试功能很有用,例如 Debug.Assert,它上面有一个 Conditional("DEBUG")。
Conditional 接受一个字符串参数。如果定义了该字符串(由编译器的预处理器确定),则编译器发出方法调用。如果未定义符号,C# 仍会编译方法,但不会编译调用。
后来,为了加强我们的观点:
Conditional 属性完全由编译器处理,无需运行时的任何合作。该方法仍然正常运行,但如果未定义符号,编译器不会发出调用。
现在,我们发生了冲突。我们不能在运行时将参数传递给编译器预处理器(告诉它是否定义了“DEBUG”),只能在编译时,但该方法只会在运行时被调用,因为那是当我们推断出我们的dynamic
值的类型时。
这就是为什么 binder 在运行时大喊实际上不能调用此方法的原因,因为这会破坏ConditionalAttribute
.
奖金:
这实际上被称为:
private static void Main(string[] args)
{
object param = null;
if (Program.<Main>o__SiteContainer0.<>p__Site1 == null)
{
Program.<Main>o__SiteContainer0.<>p__Site1 = CallSite<Action<CallSite, Type, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "Assert", null, typeof(Program), new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
}
Action<CallSite, Type, object> arg_CB_0 = Program.<Main>o__SiteContainer0.<>p__Site1.Target;
CallSite arg_CB_1 = Program.<Main>o__SiteContainer0.<>p__Site1;
Type arg_CB_2 = typeof(Debug);
if (Program.<Main>o__SiteContainer0.<>p__Site2 == null)
{
Program.<Main>o__SiteContainer0.<>p__Site2 = CallSite<Func<CallSite, Type, object, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.None, "whatever", null, typeof(Program), new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
}
arg_CB_0(arg_CB_1, arg_CB_2, Program.<Main>o__SiteContainer0.<>p__Site2.Target(Program.<Main>o__SiteContainer0.<>p__Site2, typeof(Program), param));