C # - Атрибуты

An attribute- это декларативный тег, который используется для передачи информации среде выполнения о поведении различных элементов, таких как классы, методы, структуры, счетчики, сборки и т. д. в вашей программе. Вы можете добавить декларативную информацию в программу с помощью атрибута. Декларативный тег обозначается квадратными скобками ([]), помещенными над элементом, для которого он используется.

Атрибуты используются для добавления в программу метаданных, таких как инструкции компилятора и другой информации, такой как комментарии, описание, методы и классы. .Net Framework предоставляет два типа атрибутов: предварительно определенные атрибуты и настраиваемые атрибуты.

Указание атрибута

Синтаксис для указания атрибута следующий:

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

Имя атрибута и его значения указываются в квадратных скобках перед элементом, к которому применяется атрибут. Позиционные параметры определяют важную информацию, а параметры имени указывают дополнительную информацию.

Предопределенные атрибуты

.Net Framework предоставляет три предопределенных атрибута:

  • AttributeUsage
  • Conditional
  • Obsolete

AttributeUsage

Предопределенный атрибут AttributeUsageописывает, как можно использовать класс настраиваемого атрибута. Он определяет типы элементов, к которым может применяться атрибут.

Синтаксис для указания этого атрибута следующий:

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

Куда,

  • Параметр validon указывает языковые элементы, на которых можно разместить атрибут. Это комбинация значений перечислителя AttributeTargets . Значение по умолчанию - AttributeTargets.All .

  • Параметр allowmultiple (необязательный) предоставляет значение для свойства AllowMultiple этого атрибута, логическое значение. Если это правда, атрибут многоразовый. По умолчанию - false (одноразовое).

  • Параметр унаследованный (необязательный) предоставляет значение для свойства Inherited этого атрибута, логическое значение. Если это правда, атрибут наследуется производными классами. Значение по умолчанию - false (не наследуется).

Например,

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

Условный

Этот предопределенный атрибут отмечает условный метод, выполнение которого зависит от указанного идентификатора предварительной обработки.

Это вызывает условную компиляцию вызовов методов в зависимости от указанного значения, например Debug или же Trace. Например, он отображает значения переменных при отладке кода.

Синтаксис для указания этого атрибута следующий:

[Conditional(
   conditionalSymbol
)]

Например,

[Conditional("DEBUG")]

В следующем примере демонстрируется атрибут -

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

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

In Main function
In Function 1
In Function 2

Устаревший

Этот предопределенный атрибут отмечает программный объект, который не следует использовать. Это позволяет вам сообщить компилятору об отказе от определенного целевого элемента. Например, когда в классе используется новый метод и вы все еще хотите сохранить старый метод в классе, вы можете пометить его как устаревший, отобразив сообщение, что следует использовать новый метод вместо старого.

Синтаксис для указания этого атрибута следующий:

[Obsolete (
   message
)]

[Obsolete (
   message,
   iserror
)]

Куда,

  • Параметр сообщения , является строка , описывающая причину , пункт устарел и что нужно использовать вместо.

  • Параметр iserror - это логическое значение. Если его значение истинно, компилятор должен рассматривать использование элемента как ошибку. Значение по умолчанию - false (компилятор выдает предупреждение).

Следующая программа демонстрирует это -

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

Когда вы пытаетесь скомпилировать программу, компилятор выдает сообщение об ошибке:

Don't use OldMethod, use NewMethod instead

Создание настраиваемых атрибутов

.Net Framework позволяет создавать настраиваемые атрибуты, которые могут использоваться для хранения декларативной информации и могут быть получены во время выполнения. Эта информация может относиться к любому целевому элементу в зависимости от критериев проектирования и потребности приложения.

Создание и использование настраиваемых атрибутов включает четыре шага:

  • Объявление настраиваемого атрибута
  • Создание настраиваемого атрибута
  • Применить настраиваемый атрибут к элементу целевой программы
  • Доступ к атрибутам через отражение

Последний шаг включает в себя написание простой программы для чтения метаданных в поисках различных обозначений. Метаданные - это данные о данных или информация, используемые для описания других данных. Эта программа должна использовать отражения для доступа к атрибутам во время выполнения. Об этом мы поговорим в следующей главе.

Объявление настраиваемого атрибута

Новый настраиваемый атрибут должен быть получен из System.Attributeкласс. Например,

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

В предыдущем коде мы объявили настраиваемый атрибут с именем DeBugInfo .

Создание настраиваемого атрибута

Давайте создадим настраиваемый атрибут с именем DeBugInfo , в котором хранится информация, полученная при отладке любой программы. Пусть он хранит следующую информацию -

  • Кодовый номер ошибки
  • Имя разработчика, обнаружившего ошибку
  • Дата последней проверки кода
  • Строковое сообщение для хранения замечаний разработчика

Класс DeBugInfo имеет три частных свойства для хранения первых трех сведений и общедоступное свойство для хранения сообщения. Следовательно, номер ошибки, имя разработчика и дата проверки являются позиционными параметрами класса DeBugInfo, а сообщение является необязательным или именованным параметром.

У каждого атрибута должен быть хотя бы один конструктор. Позиционные параметры следует передавать через конструктор. В следующем коде показан класс 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;
      }
   }
}

Применение настраиваемого атрибута

Атрибут применяется, помещая его непосредственно перед своей целью -

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

В следующей главе мы получаем атрибутивную информацию с помощью объекта класса Reflection.