Атрибуты в классе UseAttrib: RemarkAttribute Примечание: В этом классе используется атрибут.
Сравнение позиционных и именованных параметров
В предыдущем примере для инициализации атрибута RemarkAttribute его конструктору была передана символьная строка с помощью обычного синтаксиса конструктора. В этом случае параметр comment конструктора RemarkAttribute () называется позиционным. Этот термин отражает тот факт, что аргумент связан с параметром по его позиции в списке аргументов. Следовательно, первый аргумент передается первому параметру, второй аргумент — второму параметру и т.д.
Но для атрибута доступны также именованные параметры, которым можно присваивать первоначальные значения по их именам. В этом случае значение имеет имя, а не позиция параметра. '
ПРИМЕЧАНИЕ
Несмотря на то что именованные параметры атрибутов, по существу, подобны именованным аргументам методов, они все же отличаются в деталях.
Именованный параметр поддерживается открытым полем или свойством, которое должно быть нестатическим и доступным только для записи. Любое поле или свойство подобного рода может автоматически использоваться в качестве именованного параметра. Значение присваивается именованному параметру с помощью соответствующего оператора, расположенного в списке аргументов при вызове конструктора атрибута. Ниже приведена общая форма объявления атрибута, включая именованные параметры.
[attrib (список_позиционных_параметров,
мменованный_параметр_1 = значение, именованный_параметр_2 = значение,...)]
Первыми указываются позиционные параметры, если они существуют. Далее следуют именованные параметры с присваиваемыми значениями. Порядок следования
Именованных параметров особого значения не имеет. Именованным параметрам не обязательно присваивать значение, и в этом случае используется значение, устанавливаемое по умолчанию.
Применение именованного параметра лучше всего показать на конкретном примере. Ниже приведен вариант класса RemarkAttribute, в который добавлено поле Supplement, предназначенное для хранения дополнительного примечания.
[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;
}
}
}
Как видите, поле 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 о in attribs) {
Console.WriteLine (o);
}
// Извлечь атрибут RemarkAttribute.
Type tRemAtt = typeof(RemarkAttribute);
RemarkAttribute ra = (RemarkAttribute)