为什么.NET的条件属性导致副作用被删除?

时间:2009-01-04 11:43:20

标签: .net conditional

我今天读到了Conditional属性。根据MSDN:

  

ConditionalAttribute应用于方法指示编译器不应将对该方法的调用编译为Microsoft中间语言(MSIL),除非定义了与ConditionalAttribute关联的条件编译符号。 / p>

行。这很清楚。因此,对方法的调用将不会被编译。但副作用呢?

[Conditional("UndefinedCondition")]
static void f1(int x) { Console.WriteLine(x); }

static int a = 0;
static void f2() { f1(++a); }

因此,当调用f2时,应删除对f1的调用。但为什么++a也被删除了?这对我没有任何意义!

4 个答案:

答案 0 :(得分:5)

是的,参数所需的任何调用也会被删除。这意味着对于典型的用例(调试版本),您将删除整个表达式,这通常是预期的。

基本上,在使用[Conditional]方法,(在C#3.0中)部分方法时,您需要非常小心 - 这些方法具有非常相似的行为如果部分方法的另一半未实现。作为示例(对于部分方法),请参见下文。请注意,已移除对HasSideEffect()的调用(取消注释Bar的另一半以查看其是否有效):

using System;
partial class Foo {
    partial void Bar(string value);
    static void Main() {
        Foo foo = new Foo();
        foo.Bar(HasSideEffect());
    }
    static string HasSideEffect() {
        Console.WriteLine("hello");
        return "world";
    }
}

partial class Foo {
    /* uncomment this
    partial void Bar(string value) {
        Console.WriteLine(value);
    }*/ 
}

答案 1 :(得分:5)

扩展Marc的答案。

这绝对是“按设计”。理解这种合理化的最好方法是考虑这个代码取而代之的是什么。这个功能以许多更清晰的方式采用了有条件编译的代码。

例如,

#if DEBUG
f1(++a);
#endif

或其他版本

#define f1(x) ...

在非调试的情况下,显然没有副作用。这与[条件]代码的行为相同。我同意它肯定不如第一个例子那么清楚,但它与第二个例子一样清晰。

答案 2 :(得分:1)

我想这是因为编译器的实现很容易。

无论如何我会害怕这些代码(即使它按预期工作)并将其写为

++a;
f1(a);

为了清楚起见。您总是可以看到执行的内容和不执行的内容。

答案 3 :(得分:1)

我还怀疑此行为的设计与C预处理器宏相同,后者通常设置为在不使用时不评估参数。