C # - Atributos

Un attributees una etiqueta declarativa que se utiliza para transmitir información al tiempo de ejecución sobre el comportamiento de varios elementos como clases, métodos, estructuras, enumeradores, ensamblajes, etc. en su programa. Puede agregar información declarativa a un programa utilizando un atributo. Una etiqueta declarativa se representa mediante corchetes ([]) colocados sobre el elemento para el que se utiliza.

Los atributos se utilizan para agregar metadatos, como la instrucción del compilador y otra información, como comentarios, descripción, métodos y clases a un programa. .Net Framework proporciona dos tipos de atributos: los atributos predefinidos y los atributos personalizados .

Especificar un atributo

La sintaxis para especificar un atributo es la siguiente:

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

El nombre del atributo y sus valores se especifican entre corchetes, antes del elemento al que se aplica el atributo. Los parámetros posicionales especifican la información esencial y los parámetros de nombre especifican la información opcional.

Atributos predefinidos

.Net Framework proporciona tres atributos predefinidos:

  • AttributeUsage
  • Conditional
  • Obsolete

Atributo Uso

El atributo predefinido AttributeUsagedescribe cómo se puede utilizar una clase de atributo personalizado. Especifica los tipos de elementos a los que se puede aplicar el atributo.

La sintaxis para especificar este atributo es la siguiente:

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

Dónde,

  • El parámetro validon especifica los elementos del idioma en los que se puede colocar el atributo. Es una combinación del valor de un enumerador AttributeTargets . El valor predeterminado es AttributeTargets.All .

  • El parámetro allowmultiple (opcional) proporciona un valor para la propiedad AllowMultiple de este atributo, un valor booleano. Si esto es cierto, el atributo es de usos múltiples. El valor predeterminado es falso (de un solo uso).

  • El parámetro heredado (opcional) proporciona un valor para la propiedad heredada de este atributo, un valor booleano. Si es cierto, las clases derivadas heredan el atributo. El valor predeterminado es falso (no heredado).

Por ejemplo,

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

Condicional

Este atributo predefinido marca un método condicional cuya ejecución depende de un identificador de preprocesamiento especificado.

Provoca la compilación condicional de llamadas a métodos, según el valor especificado, como Debug o Trace. Por ejemplo, muestra los valores de las variables mientras depura un código.

La sintaxis para especificar este atributo es la siguiente:

[Conditional(
   conditionalSymbol
)]

Por ejemplo,

[Conditional("DEBUG")]

El siguiente ejemplo demuestra el atributo:

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

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

In Main function
In Function 1
In Function 2

Obsoleto

Este atributo predefinido marca una entidad de programa que no debe utilizarse. Le permite informar al compilador que descarte un elemento de destino en particular. Por ejemplo, cuando se usa un método nuevo en una clase y aún desea conservar el método anterior en la clase, puede marcarlo como obsoleto mostrando un mensaje en el que se debe usar el método nuevo, en lugar del método anterior.

La sintaxis para especificar este atributo es la siguiente:

[Obsolete (
   message
)]

[Obsolete (
   message,
   iserror
)]

Dónde,

  • El mensaje de parámetro es una cadena que describe la razón por la que el artículo es obsoleto y qué usar en su lugar.

  • El parámetro iserror , es un valor booleano. Si su valor es verdadero, el compilador debería tratar el uso del elemento como un error. El valor predeterminado es falso (el compilador genera una advertencia).

El siguiente programa demuestra esto:

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

Cuando intenta compilar el programa, el compilador muestra un mensaje de error que indica:

Don't use OldMethod, use NewMethod instead

Creación de atributos personalizados

.Net Framework permite la creación de atributos personalizados que se pueden usar para almacenar información declarativa y se pueden recuperar en tiempo de ejecución. Esta información se puede relacionar con cualquier elemento de destino dependiendo de los criterios de diseño y la necesidad de la aplicación.

La creación y el uso de atributos personalizados implica cuatro pasos:

  • Declarar un atributo personalizado
  • Construyendo el atributo personalizado
  • Aplicar el atributo personalizado en un elemento de programa de destino
  • Acceder a los atributos a través de la reflexión

El último paso consiste en escribir un programa simple para leer los metadatos y encontrar varias notaciones. Los metadatos son datos sobre datos o información que se utilizan para describir otros datos. Este programa debería utilizar reflejos para acceder a los atributos en tiempo de ejecución. Esto lo discutiremos en el próximo capítulo.

Declaración de un atributo personalizado

Un nuevo atributo personalizado debe derivarse de la System.Attributeclase. Por ejemplo,

//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

En el código anterior, hemos declarado un atributo personalizado llamado DeBugInfo .

Construir el atributo personalizado

Construyamos un atributo personalizado llamado DeBugInfo , que almacena la información obtenida al depurar cualquier programa. Deje que almacene la siguiente información:

  • El número de código del error.
  • Nombre del desarrollador que identificó el error
  • Fecha de la última revisión del código
  • Un mensaje de cadena para almacenar los comentarios del desarrollador.

La clase DeBugInfo tiene tres propiedades privadas para almacenar las tres primeras información y una propiedad pública para almacenar el mensaje. Por lo tanto, el número de error, el nombre del desarrollador y la fecha de revisión son los parámetros posicionales de la clase DeBugInfo y el mensaje es un parámetro opcional o nombrado.

Cada atributo debe tener al menos un constructor. Los parámetros posicionales deben pasarse a través del constructor. El siguiente código muestra la clase 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;
      }
   }
}

Aplicar el atributo personalizado

El atributo se aplica colocándolo inmediatamente antes de su objetivo:

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

En el siguiente capítulo, recuperamos información de atributos usando un objeto de clase Reflection.