2010-01-14 36 views
5

我想知道为什么当你在基类中的虚拟方法上放置System.Diagnostics.Conditional(“DEBUG”)属性时,你不会在派生类上得到编译器错误,覆盖相同的虚拟方法,但在条件不满足时没有条件属性。例如:虚拟功能上的条件属性

public class MyBaseClass 
{ 
    [System.Diagnostics.Conditional("DEBUG")] 
    public virtual void Test() 
    { 
     //Do something 
    } 
} 

public class MyDerivedClass : MyBaseClass 
{ 
    public override void Test() 
    { 
     //Do something different 
    } 
} 

似乎没有被定义时DEBUG,条件将基本上使一个sitation其中重写方法不能存在,因为在实际的IL输出没有虚函数。然而在我的测试中,编译器似乎无论如何都能生成代码。条件是否仅仅抛出函数体的IL,但不对类签名做任何实际的改变?

+0

切线:将条件属性从基类的虚拟位置重定位到派生类的覆盖会导致编译器错误。考虑到答案中详述的行为,这是有道理的。 – devgeezer 2011-09-07 14:28:21

回答

5

我认为这是因为该属性仅通过忽略对该方法的调用来指示该方法不可调用,但该方法确实存在。

编辑: 我继续前进,尝试了一下,如果您在Reflector中检查以下代码的发布版本,您会注意到对Test方法的调用不存在。

public class TestClass 
    { 
     [ConditionalAttribute("DEBUG")] 
     public static void Test() 
     { 
      Console.WriteLine("Blierpie"); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Starting test"); 
      TestClass.Test(); 
      Console.WriteLine("Finished test"); 
      Console.ReadKey(); 
     } 
    } 
+0

是的,没错 - MSDN认为“表示编译器应该忽略方法调用或属性,除非定义了指定的条件编译符号。” – Matthias 2010-01-14 19:32:00

1

Anton是对的。该函数在那里,但直接调用它会被忽略。但是你仍然可以使用反射来调用它。

 MyDerivedClass myDerivedClass = new MyDerivedClass(); 
     //Following will not work in Release configuration 
     myDerivedClass.Test(); 
     //But it exist and you can still call it using reflection 
     myDerivedClass.GetType().GetMethod("Test").Invoke(myDerivedClass, null); 
     //It name will still appear. 
     foreach (MethodInfo method in myDerivedClass.GetType().GetMethods()) 
      Console.WriteLine(method.Name); 
1

更有趣的情况是这样的一个:

class Program { 
    static void Main(string[] args) { 
     new Derived().Test(); 
    } 
} 
public class Base { 
    [System.Diagnostics.Conditional("DEBUG")] 
    public virtual void Test() { Console.WriteLine("base"); } 
} 

public class Derived : Base { 
    public override void Test() { 
     base.Test(); 
    } 
} 

}

如果您在本运行程序Ildasm.exe,你会看到,它实际上发出Base.Test()方法,但省略base.Test()调用。换句话说,[条件]不会省略方法,它会省略方法调用。