KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Герберт Шилдт - C# 4.0: полное руководство

Герберт Шилдт - C# 4.0: полное руководство

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Герберт Шилдт, "C# 4.0: полное руководство" бесплатно, без регистрации.
Перейти на страницу:

  public string Supplement;


  public RemarkAttribute(string comment) {

    pri_remark = comment;

    Supplement = "Отсутствует";

  }


  public string Remark {

    get {

      return pri_remark;

    }

  }

}


Как видите, поле Supplement инициализируется в конструкторе символьной строкой "Отсутствует". Другого способа присвоить ему первоначальное значение в конструкторе не существует. Но поскольку поле Supplement является открытым в классе RemarkAttribute, его можно использовать в качестве именованного параметра, как показано ниже.


[RemarkAttribute("В этом классе используется атрибут.",

Supplement = "Это дополнительная информация.")]

class UseAttrib {

// ...

}


Обратите особое внимание на вызов конструктора класса RemarkAttribute. В этом конструкторе первым, как и прежде, указывается позиционный параметр, а за ним через запятую следует именованный параметр Supplement, которому присваивается конкретное значение. И наконец, закрывающая скобка, ), завершает вызов конструктора. Таким образом, именованный параметр инициализируется в вызове конструктора. Этот синтаксис можно обобщить: позиционные параметры должны указываться в том порядке, в каком они определены в конструкторе, а именованные параметры — в произвольном порядке и вместе с присваиваемыми им значениями.

Ниже приведена программа, в которой демонстрируется применение поля Supplement в качестве именованного параметра атрибута.


// Использовать именованный параметр атрибута.

using System;

using System.Reflection;


[AttributeUsage(AttributeTargets.All)]

public class RemarkAttribute : Attribute {

  string pri_remark; // базовое поле свойства Remark

  public string Supplement; // это именованный параметр


  public RemarkAttribute(string comment) {

    pri_remark = comment;

    Supplement = "Отсутствует";

  }


  public string Remark {

    get {

      return pri_remark;

    }

  }

}


[RemarkAttribute("В этом классе используется атрибут.",

Supplement = "Это дополнительная информация.")]

class UseAttrib {

// ...

}


class NamedParamDemo {

  static void Main() {

    Type t = typeof(UseAttrib);


    Console.Write("Атрибуты в классе " + t.Name + ": ");

    object[] attribs = t.GetCustomAttributes(false);

    foreach(object o in attribs) {

      Console.WriteLine (o);

    }


    // Извлечь атрибут RemarkAttribute.

    Type tRemAtt = typeof(RemarkAttribute);

    RemarkAttribute ra = (RemarkAttribute)

    Attribute.GetCustomAttribute(t, tRemAtt);


    Console.Write("Примечание: ");

    Console.WriteLine(ra.Remark);

    Console.Write("Дополнение: ") ;

    Console.WriteLine(ra.Supplement);

  }

}


При выполнении этой программы получается следующий результат.


Атрибуты в классе UseAttrib: RemarkAttribute

Примечание: В этом классе используется атрибут.

Дополнение: Это дополнительная информация.


Прежде чем перейти к следующему вопросу, следует особо подчеркнуть, что поле pri_remark нельзя использовать в качестве именованного параметра, поскольку оно закрыто в классе RemarkAttribute. Свойство Remark также нельзя использовать в качестве именованного параметра, потому что оно доступно только для чтения. Напомним, что в качестве именованных параметров могут служить только открытые поля и свойства.

Открытое и доступное только для чтения свойство может использоваться в качестве именованного параметра таким же образом, как и открытое поле. В качестве примера ниже показано, как автоматически реализуемое свойство Priority типа int вводится в класс RemarkAttribute.


// Использовать свойство в качестве именованного параметра атрибута.

using System;

using System.Reflection;


[AttributeUsage(AttributeTargets.All)]

public class RemarkAttribute : Attribute {

  string pri_remark; // базовое поле свойства Remark

  public string Supplement; // это именованный параметр


  public RemarkAttribute(string comment) {

    pri_remark = comment;

    Supplement = "Отсутствует";

    Priority = 1;

  }


  public string Remark {

    get {

      return pri_remark;

    }

  }


  // Использовать свойство в качестве именованного параметра,

  public int Priority { get; set; }

}


[RemarkAttribute("В этом классе используется атрибут.",

        Supplement = " Это дополнительная информация.",

        Priority = 10)]

class UseAttrib {

// ...

}


class NamedParamDemo {

  static void Main() {

    Type t = typeof(UseAttrib);

    Console.Write("Атрибуты в классе " + t.Name + ": ");

    object[] attribs = t.GetCustomAttributes(false);

    foreach(object o in attribs) {

      Console.WriteLine(o);

    }

    // Извлечь атрибут RemarkAttribute.

    Type tRemAtt = typeof(RemarkAttribute);

    RemarkAttribute ra = (RemarkAttribute)

    Attribute.GetCustomAttribute(t, tRemAtt);

    Console.Write("Примечание: ") ;

    Console.WriteLine(ra.Remark);

    Console.Write("Дополнение: ") ;

    Console.WriteLine(ra.Supplement);

    Console.WriteLine("Приоритет: " + ra.Priority);

  }

}


Вот к какому результату приводит выполнение этого кода.


Атрибуты в классе UseAttrib: RemarkAttribute

Примечание: В этом классе используется атрибут.

Дополнение: Это дополнительная информация.

Приоритет: 10


В данном примере обращает на себя внимание порядок указания атрибутов перед классом UseAttrib, как показано ниже.


[RemarkAttribute("В этом классе используется атрибут.",

      Supplement = " Это дополнительная информация.",

      Priority = 10)]

class UseAttrib {

// ...

}


Именованные параметры атрибутов Supplement и Priority не обязательно указывать в каком-то определенном порядке. Порядок их указания можно свободно изменить, не меняя сами атрибуты.

И последнее замечание: тип параметра атрибута (как позиционного, так и именованного) должен быть одним из встроенных простых типов, object, Туре, перечислением или одномерным массивом одного из этих типов.


Встроенные атрибуты

В C# предусмотрено несколько встроенных атрибутов, но три из них имеют особое значение, поскольку они применяются в самых разных ситуациях. Это атрибуты AttributeUsage, Conditional и Obsolete, рассматриваемые далее по порядку.


Атрибут AttributeUsage

Как упоминалось ранее, атрибут AttributeUsage определяет типы элементов, к которым может быть применен объявляемый атрибут. AttributeUsage — это, по существу, еще одно наименование класса System.AttributeUsageAttribute. У него имеется следующий конструктор:


AttributeUsage(AttributeTargets validOn)


где validOn обозначает один или несколько элементов, к которым может быть применен объявляемый атрибут, тогда как AttributeTargets — перечисление, в котором определяются приведенные ниже значения.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*