2010-01-14 17 views
5

Me pregunto por qué cuando pones un atributo System.Diagnostics.Conditional ("DEBUG") en un método virtual en una clase base que no obtienes los errores del compilador en las clases derivadas que anula ese mismo método virtual pero no tiene el atributo condicional cuando la condición no se cumple. Ejemplo:Atributo condicional en una función virtual

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

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

Parece que cuando DEBUG no está definido, el condicional esencialmente haría un sitation donde el método de reemplazo no puede existir porque no hay función virtual en la salida IL real. Sin embargo, en mis pruebas, el compilador parece generar el código de una manera u otra. ¿El condicional simplemente descarta el IL para el cuerpo de la función pero no realiza ningún cambio real en la firma de la clase?

+0

tangencial: la reubicación del atributo condicional de la clase base virtual a la anulación de la clase derivada genera un error de compilación. Esto tiene sentido considerando el comportamiento detallado en la respuesta. – devgeezer

Respuesta

5

Creo que esto se debe a que el atributo solo indica que el método no se puede llamar ignorando las llamadas a ese método, pero el método existe.

Edité: Continué y experimenté un poco con esto y si inspecciona una compilación de lanzamiento del siguiente código en Reflector, notará que la llamada al método de prueba está ausente.

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

Sí, es correcto - MSDN dice "Indica a los compiladores que una llamada o atributo de método debe ignorarse a menos que se defina un símbolo de compilación condicional especificado". – Matthias

1

Anton es correcto. La función está ahí pero se ignora una llamada directa a ella. Pero aún puedes llamarlo usando reflexión.

 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

El caso más interesante es éste:

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(); 
    } 
} 

}

Si ejecuta Ildasm.exe en esto, verá que en realidad emite la Base.Test() método, pero omite la llamada base.Test(). En otras palabras, [Condicional] no omite los métodos, omite las llamadas a métodos.

Cuestiones relacionadas