Страница 267 из 502
Как видите, поле Supplement инициализируется в конструкторе символьной строкой "Отсутствует". Другого способа присвоить ему первоначальное значение в конструкторе не существует. Но поскольку поле Supplement является открытым в классе RemarkAttribute, его можно использовать в качестве именованного параметра, как показано ниже.
<b>[RemarkAttribute("В этом классе используется атрибут.",</b>
<b>Supplement = "Это дополнительная информация.")]</b>
<b>class UseAttrib {</b>
<b>// ...</b>
<b>}</b>
Обратите особое внимание на вызов конструктора класса RemarkAttribute. В этом конструкторе первым, как и прежде, указывается позиционный параметр, а за ним через запятую следует именованный параметр Supplement, которому присваивается конкретное значение. И наконец, закрывающая скобка, ), завершает вызов конструктора. Таким образом, именованный параметр инициализируется в вызове конструктора. Этот синтаксис можно обобщить: позиционные параметры должны указываться в том порядке, в каком они определены в конструкторе, а именованные параметры — в произвольном порядке и вместе с присваиваемыми им значениями.
Ниже приведена программа, в которой демонстрируется применение поля Supplement в качестве именованного параметра атрибута.
<b>// Использовать именованный параметр атрибута.</b>
<b>using System;</b>
<b>using System.Reflection;</b>
<b>[AttributeUsage(AttributeTargets.All)]</b>
<b>public class RemarkAttribute : Attribute {</b>
<b> string pri_remark; // базовое поле свойства Remark</b>
<b> public string Supplement; // это именованный параметр</b>
<b> public RemarkAttribute(string comment) {</b>
<b> pri_remark = comment;</b>
<b> Supplement = "Отсутствует";</b>
<b> }</b>
<b> public string Remark {</b>
<b> get {</b>
<b> return pri_remark;</b>
<b> }</b>
<b> }</b>
<b>}</b>
<b>[RemarkAttribute("В этом классе используется атрибут.",</b>
<b>Supplement = "Это дополнительная информация.")]</b>
<b>class UseAttrib {</b>
<b>// ...</b>
<b>}</b>
<b>class NamedParamDemo {</b>
<b> static void Main() {</b>
<b> Type t = typeof(UseAttrib);</b>
<b> Console.Write("Атрибуты в классе " + t.Name + ": ");</b>
<b> object[] attribs = t.GetCustomAttributes(false);</b>
<b> foreach(object o in attribs) {</b>
<b> Console.WriteLine (o);</b>
<b> }</b>
<b> // Извлечь атрибут RemarkAttribute.</b>
<b> Type tRemAtt = typeof(RemarkAttribute);</b>
<b> RemarkAttribute ra = (RemarkAttribute)</b>
<b> Attribute.GetCustomAttribute(t, tRemAtt);</b>
<b> Console.Write("Примечание: ");</b>
<b> Console.WriteLine(ra.Remark);</b>
<b> Console.Write("Дополнение: ") ;</b>
<b> Console.WriteLine(ra.Supplement);</b>
<b> }</b>
<b>}</b>
При выполнении этой программы получается следующий результат.
<b>Атрибуты в классе UseAttrib: RemarkAttribute</b>
<b>Примечание: В этом классе используется атрибут.</b>
<b>Дополнение: Это дополнительная информация.</b>
Прежде чем перейти к следующему вопросу, следует особо подчеркнуть, что поле pri_remark нельзя использовать в качестве именованного параметра, поскольку оно закрыто в классе RemarkAttribute. Свойство Remark также нельзя использовать в качестве именованного параметра, потому что оно доступно только для чтения. Напомним, что в качестве именованных параметров могут служить только открытые поля и свойства.
Открытое и доступное только для чтения свойство может использоваться в качестве именованного параметра таким же образом, как и открытое поле. В качестве примера ниже показано, как автоматически реализуемое свойство Priority типа int вводится в класс RemarkAttribute.
<b>// Использовать свойство в качестве именованного параметра атрибута.</b>
<b>using System;</b>
<b>using System.Reflection;</b>
<b>[AttributeUsage(AttributeTargets.All)]</b>