2010-01-14 8 views
5

Je me demande pourquoi, lorsque vous attribuez un attribut System.Diagnostics.Conditional ("DEBUG") à une méthode virtuelle dans une classe de base, vous n'obtenez pas d'erreurs de compilation sur les classes dérivées substituez cette même méthode virtuelle mais ne possédez pas l'attribut conditionnel lorsque la condition n'est pas remplie. Exemple:Attribut conditionnel sur une fonction virtuelle

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

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

Il semble que lorsque DEBUG n'est pas défini, le conditionnel serait essentiellement faire une sitation lorsque la méthode de remplacement ne peut pas exister parce qu'il n'y a pas de fonction virtuelle dans la sortie de IL réelle. Pourtant, dans mes tests, le compilateur semble générer le code d'une manière ou d'une autre. Est-ce que le conditionnel jette simplement l'IL pour le corps de la fonction mais n'apporte pas de vrais changements à la signature de la classe?

+0

tangentiellement: le déplacement de l'attribut conditionnel de la classe virtuelle de la classe de base vers la classe dérivée entraîne une erreur de compilateur. Cela est logique compte tenu du comportement détaillé dans la réponse. – devgeezer

Répondre

5

Je pense que c'est parce que l'attribut indique seulement que la méthode n'est pas appelable en ignorant les appels à cette méthode, mais la méthode existe.

Édition: Je suis allé de l'avant et j'ai expérimenté un peu avec ceci et si vous inspectez une version release du code suivant dans Reflector, vous remarquerez que l'appel à la méthode Test est absent.

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

Oui, c'est vrai - MSDN dit "Indique aux compilateurs qu'un appel de méthode ou un attribut doit être ignoré à moins qu'un symbole de compilation conditionnel spécifié soit défini.". – Matthias

1

Anton est droite. La fonction est là mais un appel direct est ignoré. Mais vous pouvez toujours l'appeler en utilisant la réflexion.

 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

Le cas le plus intéressant est celui-ci:

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 vous exécutez Ildasm.exe sur ce point, vous verrez qu'il émet en fait le Base.test() méthode, mais omet l'appel de base.Test(). En d'autres termes, [Conditionnel] n'omet pas les méthodes, il omet les appels de méthode.

Questions connexes