为什么总是对条件方法的参数进行类型检查?

时间:2017-04-06 23:22:41

标签: c# conditional-attribute

如果编译了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。 :)

1 个答案:

答案 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块中的任何内容都被词法分析器视为   一条评论。这就像你只是删除了整个内容   阻止并用空格替换它。但删除呼叫网站   取决于条件属性发生在语义分析时间;   执行语义分析所必需的一切必须是   本