Г. Шилдт - Полный справочник по C# (1160789), страница 83
Текст из файла (страница 83)
Отражение представляет собой средство, с помощью которогоможно получить информацию о типе. Используя эту информацию, во время выполнения программы можно создавать объекты, а затем работать с ними. Это средствообладает большой эффективностью, поскольку оно позволяет динамически расширятьфункции, выполняемые программой. Атрибут предназначен для описания элементовСопрограммы. Например, можно определить атрибуты для классов, методов и полей.Информацию об атрибутах можно запрашивать и получать во время выполненияпрограммы.
Для поддержки атрибутов используются средства как динамической идентификации типов, так и отражения соответствующей информации.инамическая идентификация типовДинамическая идентификация типов (runtime type identification — RTTI) позволяетопределить тип объекта во время выполнения программы, что необходимо во многихситуациях. Например, можно совершенно точно узнать, на объект какого типа в действительности указывает ссылка на базовый класс. Еще одно применение RTTI — заранее проверить, удачно ли будет выполнена операция приведения типа, не допустиввозникновения исключения, связанного с некорректно заданной операцией приведения типа. Динамическая идентификация типов также является ключевым компонентом средства отражения (информации о типе).В С# предусмотрено три ключевых слова, которые поддерживают динамическуюидентификацию типов: i s , as и typeof.
Рассмотрим назначение каждого из них вотдельности.Проверка типа с помощью ключевого слова i sС помощью оператора i s можно определить, имеет ли рассматриваемый объектзаданный тип. Общая форма его записи имеет следующий вид:выражение i s ТИПЗдесь тип элемента выражение сравнивается с элементом ТИП. ЕСЛИ ТИП элементавыражение совпадает (или совместим) с элементом ТИП, результат выполнения операции принимается равным значению ИСТИНА. В противном случае — значениюЛОЖЬ. Следовательно, если результат истинен, выражение можно привести к типу,заданному элементом ТИП.Рассмотрим пример использования оператора i s .// Демонстрация выполнения оператора i s .using System;c l a s s A {}c l a s s В : A {}class Usels {public static void Main() {A a = new A () ;В b = new В();450Часть I.
Язык С#if(a is A) Console.WriteLine("Объект а имеет тип A . " ) ;if(b is A)Console.WriteLine("Объект b совместим с типом А, " +"поскольку его тип выведен из типа А . " ) ;if(a is В)Console.WriteLine("Этот текст не будет отображен, " +"поскольку объект а не выведен из класса В.")if(b is В) Console.WriteLine("Объект b имеет тип В . " ) ;if(a is object) Console.WriteLine("а — это объект.");Результаты выполнения этой программы таковы:Объект а имеет тип А.Объект b совместим с типом А, поскольку его тип выведен из типа А.Объект b имеет тип В.а -- это объект.fНесмотря на то что все сообщения в этой программе говорят сами за себя, некотоbie из них все же требуют пояснений. Обратите внимание на следующую инструкцию:i f ( b i s A)Console.WriteLine("Объект b совместим с типом А, " +"поскольку его тип выведен из типа А .
" ) ;В данном случае i f-инструкция выполнилась успешно, поскольку переменная bявляется ссылкой типа в, который выведен из типа А. Следовательно, объект b совместим с типом А. Однако обратное утверждение не является справедливым. Привыполнении строки кодаi f ( a i s В)Console.WriteLine("Этот текст не будет отображен, " +"поскольку объект а не выведен из класса В . " ) ;Iif-инструкция успехом не увенчается, поскольку объект а имеет тип А, который невыведен из типа в. Следовательно, объект а и класс в несовместимы по типу.Использование оператора asИногда во время работы программы требуется выполнить операцию приведениятипов, не генерируя исключение в случае, если попытка окажется неудачной. Дляэтого предусмотрен оператор as, формат которого таков:выражение as типНетрудно догадаться, что используемый здесь элемент выражение участвует в попытке приведения его к типу, заданному элементом тип.
В случае успешного выполнения этой операции возвращается ссылка на тип. В противном случае возвращаетсянулевая ссылка.Оператор a s в некоторых случаях предлагает удобную альтернативу оператору i s .Рассмотрим, например, следующую программу, в которой оператор i s позволяет предотвратить неверное приведение типов:// Использование оператора i s для предотвращения// неверной операции приведения типов.using System;c l a s s A {}c l a s s В : А {}Глава 17.
Динамическая идентификация типов, отражение и атрибуты451class CheckCast {public static void Main() {A a = new A ( ) ;В b = new В();// Проверяем, можно ли объект а привести к типу В.if(a is В) // При положительном результате выполняем// операцию приведения типов,b = (В) а;else // В противном случае операция приведения// типов опускается,b = null;if(b==null)Console.WriteLine("Операция приведения типов b = (В) а НЕ РАЗРЕШЕНА.");elseConsole.WriteLine("Операция приведения типов b = (В) а разрешена.")Результаты выполнения этой программы таковы:Операция приведения b = (В) а НЕ РАЗРЕШЕНА.Как подтверждают эти результаты, поскольку тип объекта а не совместим с типомв, операция приведения объекта а к типу в недопустима, и ее выполнение предотвращается с помощью инструкции if.
Как видите, реализация такого подхода требуетвыполнения двух этапов. Первый состоит в подтверждении обоснованности операцииприведения типов, а второй — в самом ее выполнении. С помощью оператора as этидва этапа можно объединить в один, как показано в следующей программе.// Демонстрация использования оператора a s .using System;class A {}class В : A {}class CheckCast {public static void Main() {A a = new A();В b = new В() ;b = a as В; // Выполняем операцию приведения типов,// если она возможна.if(b==null)Console.WriteLine("Операция приведения типов " +"b = (В) а НЕ РАЗРЕШЕНА.");elseConsole.WriteLine("Операция приведения типов b = (В) а разрешена.");Вот результаты выполнения этой программы:Операция приведения типов b = (В) а НЕ РАЗРЕШЕНА.452Часть I.
Язык С#В этой версии оператор as проверяет допустимость операции приведения типов,а затем, если она законна, выполняет ее, причем все это реализуется в одной инструкции.Использование оператора typeofНесмотря на полезность операторов as и i s , они просто проверяют (причем каждый по-своему) совместимость двух типов.
Программист же зачастую сталкивается снеобходимостью получить информацию о типе данных. Для таких случаев в С# предусмотрен оператор typeof. Его назначение состоит в считывании объекта классаSystem.Type для заданного типа. Используя этот объект, можно определить характеристики конкретного типа данных.Оператор typeof используется в следующем формате:typeof(тип)Здесь элемент тип означает тип, информацию о котором мы хотим получить. Объект типа Туре, возвращаемый при выполнении оператора typeof, инкапсулирует информацию, связанную с заданным типом.Получив Туре-объект, можно обращаться к информации о заданном типе, используя различные свойства, поля и методы, определенные в классе Туре.
Класс Туре содержит множество членов, но их обсуждение мы отложим до следующего раздела, посвященного отражению информации о типе. Однако, чтобы все же продемонстрировать одно из возможных применений класса Туре, рассмотрим программу, в которойиспользуются три его свойства: FullName, I s C l a s s и I s A b s t r a c t . СвойствоFullName позволяет получить полное имя типа. Свойство I s C l a s s возвращает значение t r u e , если типом объекта является класс. Свойство I s A b s t r a c t возвращает значение t r u e , если рассматриваемый класс является абстрактным.// Демонстрация использования оператора typeof.using System;using System.10;class UseTypeof {public s t a t i c void Main() {Type t = typeof(StreamReader);Console.WriteLine(t.FullName);if (t.
IsClass) Console. WriteLine ("Это класс") ;if(t.IsAbstract)Console.WriteLine("Это абстрактный класс.");else Console.WriteLine("Это конкретный класс.");(При выполнении этой программы получены такие результаты:System.10.StreamReaderЭто класс.Это конкретный класс.Эта программа получает объект типа Туре с описанием типа StreamReader. Затемона отображает полное имя этого типа, определяет, класс ли это и является ли он абстрактным.Глава 17.
Динамическая идентификация типов, отражение и атрибуты453Ш ОтражениеКак упоминалось в начале этой главы, отражение (reflection) — это средство С#,которое позволяет получить информацию о типе. Термин отражение произошел отхарактера процесса: объект класса Туре воспроизводит, или отражает, базовый тип,который он представляет. Для получения интересующей вас информации вы "задаетевопросы" объекту класса Туре, а он возвращает (отражает) для вас информацию, связанную с этим типом.
Отражение — мощный механизм, позволяющий узнать характеристики типа, точное имя которого становится известным только во время выполнения программы, и соответствующим образом использовать их.Многие классы, которые поддерживают средство отражения, являются частью интерфейса .NET Reflection API, который определен в пространстве именSystem.Reflection. Таким образом, в программы, которые используют средство отражения, обычно включается следующая инструкция:I using S y s t e m . R e f l e c t i o n ;Ядро подсистемы отображения: класс system.