Динамическая идентификация типов (RTTI) позволяет определить тип объекта во время выполнения программы. Она оказывается полезной по целому ряду причин. В част ности, по ссылке на базовый класс можно довольно точно определить тип объекта, доступного по этой ссылке. Ди намическая идентификация типов позволяет также прове рить заранее, насколько удачным будет исход приведения типов, предотвращая исключительную ситуацию в связи с неправильным приведением типов. Кроме того, динамиче ская идентификация типов является главной составляющей рефлексии.
Для поддержки динамической идентификации типов в С# предусмотрены три ключевых слова: is, as и typeof. Каждое из этих ключевых слов рассматривается да лее по очереди. Проверка типа с помощью оператора is
Конкретный тип объекта можно определить с помощью оператора is. Ниже при ведена его общая форма: выражение is тип
где выражение обозначает отдельное выражение, описывающее объект, тип которого проверяется. Если выражение имеет совместимый или такой же тип, как и проверяе мый тип, то результат этой операции получается истинным, в противном случае — ложным. Так, результат будет истинным, если выражение имеет проверяемый тип в той или иной форме. В операторе is оба типа определяются как совместимые, если они одного и того же типа или если предусмотрено преобразование ссылок, упаковка или распаковка.
Ниже приведен пример применения оператора is. // Продемонстрировать применение оператора is. using System; class A {} class В : A {} class UseIs { static void Main { A a = new A; В b = new В; if(a is A) Console.WriteLine("а имеет тип A"); if(b is A) Console.WriteLine("b совместим с А, поскольку он производный от А"); if(a is В) Console.WriteLine("Не выводится, поскольку а не производный от В"); if(b is В) Console.WriteLine("В имеет тип В"); if(a is object) Console.WriteLine("а имеет тип object"); } }
Вот к какому результату приводит выполнение этого кода. а имеет тип А b совместим с А, поскольку он производный от А b имеет тип В а имеет тип object
Большая часть выражений is в приведенном выше примере не требует пояснений, но два из них необходимо все же разъяснить. Прежде всего, обратите внимание на сле дующую строку кода. if(b is A) Console.WriteLine("b совместим с А, поскольку он производный от А");
Условный оператор if выполняется, поскольку b является объектом типа В, произ водным от типа А. Но обратное несправедливо. Так, если в строке кода if(a is В) Console.WriteLine("Не выводится, поскольку а не производный от В");
условный оператор if не выполняется, поскольку а является объектом типа А, не про изводного от типа В. Поэтому а не относится к типу В. Применение оператора as
Иногда преобразование типов требуется произвести во время выполнения, но не генерировать исключение, если исход этого преобразования окажется неудачным, что вполне возможно при приведении типов. Для этой цели служит оператор as, имею щий следующую общую форму: выражение as тип
где выражение обозначает отдельное выражение, преобразуемое в указанный тип. Если исход такого преобразования оказывается удачным, то возвращается ссылка на тип, а иначе — пустая ссылка. Оператор as может использоваться только для преоб разования ссылок, идентичности, упаковки, распаковки.
В некоторых случаях оператор as может служить удобной альтернативой операто ру is. В качестве примера рассмотрим следующую программу, в которой оператор is используется для предотвращения неправильного приведения типов. // Использовать оператор is для предотвращения неправильного приведения типов. using System; class А {} class В : А {} class CheckCast { static void Main { A a = new A; В b = new В; // Проверить, можно ли привести а к типу В. if(a is В) // если да, то выполнить приведение типов b = (В) а; else // если нет, то пропустить приведение типов b = null; if(b==null) Console.WriteLine("Приведение типов b = (В) HE допустимо."); else Console.WriteLine("Приведение типов b = (В) допустимо."); } }
Эта программа дает следующий результат. Приведение типов b = (В) НЕ допустимо.