Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 105
Текст из файла (страница 105)
Так, если в классе СяедгггтЬ имеется атрибут Нещаг)сдггг1Ьпге, то для получения ссылки на этот атрибут можно воспользоваться следующей последовательностью кода: // Получить экземпляр объекта класса МещЬег1пто, // связанного с классом, содержащим // атрибут НещагнлггггЬпге. туре С Суреок(пяеАССг1Ы; // Извлечь атрибут Нещагяаггг1Ьпге. туре снещАсс = суреог(нещагкАссггьпсе)т НеиагкАССг1Ьпге га = (НещагНАССг1Ьпге) АССг1Ьпге. Пегспягощаггг1Ьпге (С, СнепАСС) т Эта последовательность кода оказывается вполне работоспособной, поскольку класс мепьегтпбо является базовым для класса туре.
Следовательно, с — это экземпляр объекта класса МещЬег1пбо. Имея ссылку на атрибут, можно получить доступ к его членам. Благодаря этому информация об атрибуте становится доступной для программы, использующей элемент, к которому присоединен атрибут. Например, в следующей строке кода выводится содержимое свойства Певали: Сопяо1е.ыг1геъ1пе(га.нещагн) Ниже приведена программа, в которой все изложенные выше особенности применения атрибутов демонстрируют на примере атрибута ПещагКАССг1ЬпСе. // Простой пример применения атрибута. пягпе Яуягещ; пв1пс Яуягещ.ае11есг1опт (АССг1Ьпгепяасе(АССг1Ьпгетагсегя.А11)] рпЫгс с1авя Нещагнаггг1Ьпге: АССг1Ьгге ( яггспе рта гещагн; // базовое поле свойства нещагн рнЬ11с Нещагнаггг1Ьпсе(астапов сояппепс) ( рг1 гещагк = сопппепс; ) риыгс ясгспс нещагк ( чес ( геспгп ргг гещагнт ) ) (неиагкассгаьчсе("в этом классе используется атрибут.")] с1аяя ОвеАССггЬ ( 548 Часть (.
Язык С№ с1аээ Агсг1ЬОево ( вгагъс ного Магп() ( Туре Г = Гуреот(пэейгсг1Ь) Сопэо1е.Иг1се("Атрибуты в классе " + Г.иаие + ": "); оЬ)есс[) ассг1Ьэ = Г.песспэсоийссг1Ьосеэ(та1эе); Гогеасн(оЬ№есс о гп асгг1Ьэ) ( Сопэо1е.иггсеъгпе(о)) ) Сопэо1е.Иггге("Примечание: "); // извлечь атрибут Кевагхйссг1Ьосе. Туре ГкемАСС Гуреот(вемагКАГГг1Ьисе); ПевагКАГСгТЬпге га (КевагкйссггЬоге) Аггггьоге.пегсоэговйггггьоге(г, гаепйгг); Сопэо1е.иг1сеъ1пе(га.веиагК); Эта программа дает следующий результат; Атрибуты в классе Пэейггг№Ь: Кемагкйссг1Ьоге Примечание: В этом классе используется атрибут. Сравнение позиционных и именованных параметров В предыдущем примере для инициализации атрибута Пепагкйссг1Ьпсе его конструктору была передана символьная строка с помощью обычного синтаксиса конструктора.
В этом случае параметр сопяпепг конструктора ПетагКАССг1Ьосе () называется позициоииььи. Этот термин отражает тот факт, что аргумент связан с параметром по его позиции в списке аргументов. Именно так действуют все методы и конструкторы в СФ. Если, например, объявляется метод сезс () чогб Геэг(глс а, бооЬ1е Ь, эсг1по с) то в следующем вызове метода сезг (): Сеэг(10, 1.1, "Ье11о"); значение 10 передается параметру а,значение 1:1 — параметру Ь,строка чпе11о" — параметру с по порядку следования аргументов, т.е.
их позиции в списке. Но для атрибута доступны также именованные параметры, которым можно присваивать первоначальные значения по их именам. В этом случае значение имеет имя, а не позиция параметра. Именованный параметр поддерживается открытым полем или свойством, которое должно быть доступным только для записи и нестатическим. Любое поле или свойство подобного рода может автоматически использоваться в качестве именованного параметра. Значение присваивается именованному параметру с помощью соответствующего оператора, располагаемого в списке аргументов при вызове конструктора атрибута. Ниже приведена общая форма объявления атрибута, включая именованные параметры.
Глава!7. Динамическая идентификация типов, рефлексия и атрибуты 549 [аккгяЬ (спнсок познцноннм» параметров, нменояаннын параметр 1 = значение, именованный параметр 2 = значение, ...)) Первыми указываются позиционные параметры, если он существуют. Далее следуют именованные параметры с присваиваемыми значениями. Порядок следования именованных параметров особого значения не имеет. Именованным параметрам не обязательно присваивать значение, и в этом случае используется значение, устанавливаемое по умолчанию. Применение именованного параметра лучше всего показать на конкретном примере. Ниже приведен вариант класса девах)кдгкг1Ьиге, в который добавлено поле яирр1евепг, предназначенное для хранения дополнительного примечания.
[Аксг1Ьисеияаде(АГГг1Ьикетагдекя.А11)] ривттс с1аяя Кевагняккг1Ьике: Аккг1Ьике ( ясг1пс ргг геваги) // базовое поле свойства Кеваги // Это поле мозно использовать з качестве // именованного параметра. риЬ11с ягг1пд Яирр1евепгт риЬ1»с КевагКАГГггЬике(якгтпд сопкяепк) ( рг1 геваги = соввепк) Яирр1евепк = "Отсутствует'Ь ) риЬ11с якг1пс Кевагн ( дег ( гесигп ргг гевагк) ) ) Как видите, поле яирр1евепг инициализируется в конструкторе символьной строкой вэтсутствует".
Другого способа присвоить ему первоначальное значение в конструкторе не существует. Но поскольку поле Яцрр1евепт является открытым в классе Кеваг)кдткг1Ьиге, его можно использовать в качестве именованного параметра, как показано ниже. [Кевагяаксг1Ьиге("В этом классе нспопьзуетск атрибут.", Яирр1евепк = "Это дополнительная информация.")) с1аяя ПяеАГГгкЬ ( О ) Обратите особое внимание на вызов конструктора класса Певаг)кдссг1Ьите. В этом конструкторе первым, как и прежде, указывается позиционный параметр, а за ним через запятую следует именованный параметр Яирр1евепк, которому присваивается конкретное значение.
И наконец, закрывающая скобка, ), завершает вызов конструктора. Таким образом, именованный параметр инициализируется в вызове конструктора. Этот синтаксис можно обобщить: позиционные параметры должны указываться в том порядке, в каком они определены в конструкторе, а именованные параметры — в произвольном порядке и вместе с присваиваемыми им значениями. 550 Часть!. Яэык С№ Ниже приведена программа, в которой демонстрируется применение поля Яцрр1етпепг в качестве именованного параметра атрибута, // Использовать именованный параметр атрибута. ця1пф Яуясепн ця1пд Яуясез.аеГ1есс1опт [Асгг1Ьцгеовафе(АГГгТЬцсеТагфесв.А11)) рцЫ1с с1аяя Незагкассг1Ьцсе: Ассг1Ьцсе ( ягг1пд рг1 гезагк) // базовое поле свойства незагк рцЫ1с ясг1пд Яцрр1езепгт // это именованный параметр рцЫ1с НезагКАГГгТЬпсе(ясг1пд соизепс) ( рг1 гезагк = соизепс; Яцрр1езепг = "Отсутствует" ) ) рцЫгс ясг1пд Незага ( чек ( гесцгп рг1 геиагкт ) ) [Незагьасгг1Ьцсе("В этом классе используется атрибут.", Яцрр1езепс = "Это дополнительная информация.")) с1аяя ПяеАГГггЬ ( // ) с1авя Назепрагазоезо ( ягаггс чогб Ма1п 0 ( туре Г = Гуреос(ояеассгьЫ ) сопяо1е.иггге("Атрибуты в классе " + г.иаие + ": "); оЬ)есс[] агсггпя = Г.Яегсцясопассг1Ьцсея(Га1яе)т Гогеасп(оп)есг о 1п ассг1Ья) ( Сопяо1е.Иггсеигпе(о)т ) // Извлечь атрибут Незаггагсг1Ьцсе.
Туре Гаеиасс - Гуреос(пезагьассг1Ьцге)) незагКАСГгАЬцге га = (Пезагнасгг1Ьцге) Ассг1пцсе.бессцясопассггпцсе(Г, Гпеплгс) сопяо1е.иг1№е("примечаниет ")) Сопяо1е.игггепьпе(га.везагк)т Сопяо1е.нг№ге("Дополнениет ")т Сопяо1е.нггсев№пе(га.вцрр1езепг)т ) ) Глава (7. Динамическая идентификации типов, рефлексия и атрибуты 551 При выполнении этой программы получается следующий результат: Атрибуты з классе ПяелггтаЪ: неваг)клггт1ьцге Примечание: В этом классе используется атрибут. Дополнение: Это дополнительная информация. Прежде чем перейти к следующему вопросу, следует особо подчеркнуть, что поле ргг гевагх нельзя использовать в качестве именованного параметра, поскольку оно закрыто в классе йеватКАгаг1Ьцте.
Свойство девах)к также нельзя использовать в качестве именованного параметра, потому что оно доступно только для чтения. Напомним, что в качестве именованных параметров могут служить только открытые поля и свойства. Открытое и доступное только для чтения свойство может использоваться в качестве именованного параметра таким же образом, как и открытое поле. В качестве примера ниже показано, как автоматически реализуемое свойство Рг1ог1су типа 1пк вводится в класс Кевагхдттг1Ьцте. // Использовать свойство в качестве именованного параметра атрибута. ця1пд 5уятев; ця1пф 5уятев.пет1естаоп; (Атстаьцсепяаде(лгттабцсетагдетя.А11)) рцЬ1гс с1аяя КевагнлттгаЬцте: АсгггЬцте ( эстгор ртг гевагнк // базовое поле свойства Невагн рцЬ11с ятгапд 5црр1евепт; // это именованный параметр рцЬ11с Невагхдттг1Ьцте(ясгапч сопппепт) ( рта геваги = сопппепт; зцрр1евепс = "Отсутствует"; Ргготгсу = 1; ) рцЬ11с ятг1пф Невагх ( дег ( гесцгп рт1 геваг)к) // использовать свойство в качестве именованного параметра.
рцьагс гпт Ртгоггту ( Четв яет; ) (Аевагнлгтггьцте("В этом классе используется атрибут." эцрр1евепс " Это дополнительная информация.", Ргаот1су = 10)) с1аяя ПяеАГГг1Ь ( // ... с1аяя Навебратавпево ( ятасгс чо1к) паап() ( 552 часть [, язык Сз туре г = гуреот(пзехггггь)к Сопво1е.нг1те("Атрибуты в классе " ь т.нане ь ": "); оЬ)ест[) аттггЬз = Г.оетсцвтоваттг1Ьцсев(та1зе) тогеасп(оЬ)ест о 1п аттггЬв) ( Сопзо1е.нггтепгпе(о); ) // Извлечь атрибут Кевагкаттг1Ьцте. туре гнепйгт = гуреев(аевагглттг1Ьцсе)к невагкатсттоцте та = (Невагхатсггоцте) Астггоцте.оетсцзтоваттг1Ьцте(Г, Гневйст); Сопво1е.Иг1те("Примечание: ")) Сопзо1е.нг1ге11пе(га.аевагк)к Сопзо1е.иг1те("Дополнение: "); Сопзо1е.нгтте11пе(га.эцрр1евепт); сопзо1е.иг1геьгпе("приоритет: " + га.ртгот1гу); ) ) Вот к какому результату приводит выполнение этого кода: Атрибуты в классе Пзеаттг1Ь: невагхастггЬцте Примечание: В этом классе используется атрибут.
Дополнение: Зто дополнительная информация. Приоритет: 10 В данном примере обращает на себя внимание порядок указания атрибутов перед классом Бзедггг1ь, как показано ниже. [аевагхаттггоцте("В этом классе используется атрибут." Зцрр1евепт = " Зто дополнительная информация.", ргьог1ту = 10)) с1авз Пяеаттг1Ь ( // ) Именованные параметры атрибутов Зцрр1евепс и рг1ог1су не обязательно указывать в каком-то определенном порядке. Порядок их указания можно свободно изменить, не меняя сами атрибуты. И последнее замечание: тип параметра атрибута (как позиционного, так и именованного) должен быть одним из встроенных простых типов, оЬЗесс, туре, перечислением или одномерным массивом одного из этих типов.