0

如果条件方法被编译掉,每次调用的参数仍然在编译时进行类型检查。这样做的动机是什么?例子:

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) { }
    }
}

需要明确的是,在此上下文中没有定义条件符号“条件”,因此从编译产生的 MSIL 中省略了方法调用。这与此处定义的规范一致,因此不足为奇。想象一个更复杂的场景:

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
    }
}

只有在定义了条件符号“condition”时,“ConditionalMethod”的调用才会包含在结果编译中。然而,在这种情况下,Bar 实际上可以向上转换为 Foo。如果编译器知道对 'ConditionalMethod' 的调用将被编译掉,它是否也应该知道如果我们关心此方法的调用,此代码将是合法的?是的,这是一个人为的、令人毛骨悚然的例子,但它有助于说明我的问题。我是出于善意的好奇而问的,因为这已经激怒了我很长一段时间了。请帮忙,乔恩·斯基特。:)

4

1 回答 1

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) { }
}

方法的签名是将调用关联到应该调用的方法的关键部分。必须在知道 Conditional 属性是否适用之前建立该关联。在上面的示例中,调用不匹配任何方法。编译器必须大胆猜测您的意思是 Blah(int,string)。但这只是一个猜测,因为签名不匹配(参数类型的顺序错误)。Blah(string,int,int) 也非常接近 - 你只是忘记了一个论点。Blahh(string,int) 也很接近 - 你只是在名称中打错了字。

对于类似的示例,请参阅Eric Lippert 的这篇博客文章(他知道这些内容)。

因此,参数必须在调用时明确定义,即使调用将被删除。事实上,除非参数存在,否则无法删除调用!

然后

条件编译指令的效果发生在lex时间;词法分析器将已删除的#if 块内的任何内容视为注释。这就像您只是删除了块的全部内容并用空格替换它。但是根据条件属性删除调用站点发生在语义分析时; 必须存在执行该语义分析所需的一切

于 2017-04-06T23:42:26.330 回答