C # - Attributs

Un attributeest une balise déclarative qui est utilisée pour transmettre des informations au runtime sur les comportements de divers éléments comme les classes, les méthodes, les structures, les énumérateurs, les assemblys, etc. dans votre programme. Vous pouvez ajouter des informations déclaratives à un programme à l'aide d'un attribut. Une balise déclarative est représentée par des crochets ([]) placés au-dessus de l'élément pour lequel elle est utilisée.

Les attributs sont utilisés pour ajouter des métadonnées, telles que les instructions du compilateur et d'autres informations telles que les commentaires, la description, les méthodes et les classes à un programme. Le .Net Framework fournit deux types d'attributs: les attributs prédéfinis et les attributs créés personnalisés .

Spécifier un attribut

La syntaxe pour spécifier un attribut est la suivante -

[attribute(positional_parameters, name_parameter = value, ...)]
element

Le nom de l'attribut et ses valeurs sont indiqués entre crochets, avant l'élément auquel l'attribut est appliqué. Les paramètres de position spécifient les informations essentielles et les paramètres de nom spécifient les informations facultatives.

Attributs prédéfinis

Le .Net Framework fournit trois attributs prédéfinis -

  • AttributeUsage
  • Conditional
  • Obsolete

AttributUsage

L'attribut prédéfini AttributeUsagedécrit comment une classe d'attributs personnalisée peut être utilisée. Il spécifie les types d'éléments auxquels l'attribut peut être appliqué.

La syntaxe pour spécifier cet attribut est la suivante -

[AttributeUsage (
   validon,
   AllowMultiple = allowmultiple,
   Inherited = inherited
)]

Où,

  • Le paramètre validon spécifie les éléments de langage sur lesquels l'attribut peut être placé. Il s'agit d'une combinaison de la valeur d'un énumérateur AttributeTargets . La valeur par défaut est AttributeTargets.All .

  • Le paramètre allowmultiple (facultatif) fournit une valeur pour la propriété AllowMultiple de cet attribut, une valeur booléenne. Si cela est vrai, l'attribut est multi-usage. La valeur par défaut est false (usage unique).

  • Le paramètre inherited (facultatif) fournit une valeur pour la propriété Inherited de cet attribut, une valeur booléenne. Si c'est vrai, l'attribut est hérité par les classes dérivées. La valeur par défaut est false (non héritée).

Par exemple,

[AttributeUsage(
   AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property, 
   AllowMultiple = true)]

Conditionnel

Cet attribut prédéfini marque une méthode conditionnelle dont l'exécution dépend d'un identificateur de prétraitement spécifié.

Il provoque la compilation conditionnelle des appels de méthode, en fonction de la valeur spécifiée telle que Debug ou Trace. Par exemple, il affiche les valeurs des variables lors du débogage d'un code.

La syntaxe pour spécifier cet attribut est la suivante -

[Conditional(
   conditionalSymbol
)]

Par exemple,

[Conditional("DEBUG")]

L'exemple suivant montre l'attribut -

#define DEBUG
using System;
using System.Diagnostics;

public class Myclass {
   [Conditional("DEBUG")]
   
   public static void Message(string msg) {
      Console.WriteLine(msg);
   }
}
class Test {
   static void function1() {
      Myclass.Message("In Function 1.");
      function2();
   }
   static void function2() {
      Myclass.Message("In Function 2.");
   }
   public static void Main() {
      Myclass.Message("In Main function.");
      function1();
      Console.ReadKey();
   }
}

Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -

In Main function
In Function 1
In Function 2

Obsolète

Cet attribut prédéfini marque une entité de programme qui ne doit pas être utilisée. Il vous permet d'informer le compilateur de supprimer un élément cible particulier. Par exemple, lorsqu'une nouvelle méthode est utilisée dans une classe et si vous souhaitez toujours conserver l'ancienne méthode dans la classe, vous pouvez la marquer comme obsolète en affichant un message indiquant que la nouvelle méthode doit être utilisée au lieu de l'ancienne.

La syntaxe pour spécifier cet attribut est la suivante -

[Obsolete (
   message
)]

[Obsolete (
   message,
   iserror
)]

Où,

  • Le message de paramètre est une chaîne décrivant la raison pour laquelle l'élément est obsolète et ce qu'il faut utiliser à la place.

  • Le paramètre iserror est une valeur booléenne. Si sa valeur est true, le compilateur doit traiter l'utilisation de l'élément comme une erreur. La valeur par défaut est false (le compilateur génère un avertissement).

Le programme suivant le démontre -

using System;

public class MyClass {
   [Obsolete("Don't use OldMethod, use NewMethod instead", true)]
   
   static void OldMethod() {
      Console.WriteLine("It is the old method");
   }
   static void NewMethod() {
      Console.WriteLine("It is the new method"); 
   }
   public static void Main() {
      OldMethod();
   }
}

Lorsque vous essayez de compiler le programme, le compilateur donne un message d'erreur indiquant -

Don't use OldMethod, use NewMethod instead

Création d'attributs personnalisés

Le .Net Framework permet la création d'attributs personnalisés qui peuvent être utilisés pour stocker des informations déclaratives et peuvent être récupérés au moment de l'exécution. Ces informations peuvent être liées à n'importe quel élément cible en fonction des critères de conception et des besoins de l'application.

La création et l'utilisation d'attributs personnalisés impliquent quatre étapes:

  • Déclaration d'un attribut personnalisé
  • Construire l'attribut personnalisé
  • Appliquer l'attribut personnalisé sur un élément de programme cible
  • Accès aux attributs par réflexion

La dernière étape consiste à écrire un programme simple pour lire les métadonnées afin de trouver diverses notations. Les métadonnées sont des données sur des données ou des informations utilisées pour décrire d'autres données. Ce programme doit utiliser des réflexions pour accéder aux attributs lors de l'exécution. Nous en discuterons dans le prochain chapitre.

Déclaration d'un attribut personnalisé

Un nouvel attribut personnalisé doit être dérivé de System.Attributeclasse. Par exemple,

//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(
   AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]

public class DeBugInfo : System.Attribute

Dans le code précédent, nous avons déclaré un attribut personnalisé nommé DeBugInfo .

Construction de l'attribut personnalisé

Construisons un attribut personnalisé nommé DeBugInfo , qui stocke les informations obtenues en déboguant n'importe quel programme. Laissez-le stocker les informations suivantes -

  • Le numéro de code du bogue
  • Nom du développeur qui a identifié le bogue
  • Date de la dernière révision du code
  • Une chaîne de message pour stocker les remarques du développeur

La classe DeBugInfo a trois propriétés privées pour stocker les trois premières informations et une propriété publique pour stocker le message. Par conséquent, le numéro de bogue, le nom du développeur et la date de révision sont les paramètres de position de la classe DeBugInfo et le message est un paramètre facultatif ou nommé.

Chaque attribut doit avoir au moins un constructeur. Les paramètres de position doivent être passés via le constructeur. Le code suivant montre la classe DeBugInfo -

//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(
   AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]

public class DeBugInfo : System.Attribute {
   private int bugNo;
   private string developer;
   private string lastReview;
   public string message;
   
   public DeBugInfo(int bg, string dev, string d) {
      this.bugNo = bg;
      this.developer = dev;
      this.lastReview = d;
   }
   public int BugNo {
      get {
         return bugNo;
      }
   }
   public string Developer {
      get {
         return developer;
      }
   }
   public string LastReview {
      get {
         return lastReview;
      }
   }
   public string Message {
      get {
         return message;
      }
      set {
         message = value;
      }
   }
}

Application de l'attribut personnalisé

L'attribut est appliqué en le plaçant immédiatement avant sa cible -

[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle {
   //member variables
   protected double length;
   protected double width;
   public Rectangle(double l, double w) {
      length = l;
      width = w;
   }
   [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
   
   public double GetArea() {
      return length * width;
   }
   [DeBugInfo(56, "Zara Ali", "19/10/2012")]
   
   public void Display() {
      Console.WriteLine("Length: {0}", length);
      Console.WriteLine("Width: {0}", width);
      Console.WriteLine("Area: {0}", GetArea());
   }
}

Dans le chapitre suivant, nous récupérons les informations d'attribut à l'aide d'un objet de classe Reflection.