Литмир - Электронная Библиотека
A
A

Несмотря на то что сами вы можете выяснить, что ссылка

object
указывает в памяти на объект совместимого с
Employee
класса, компилятор сделать подобное не в состоянии, поскольку это не будет известно вплоть до времени выполнения. Чтобы удовлетворить компилятор, понадобится применить явное приведение, которое и является вторым правилом: в таких случаях вы можете явно приводить "вниз", используя операцию приведения С#. Базовый шаблон, которому нужно следовать при выполнении явного приведения, выглядит так:

<i>(класс_к_которому_нужно_привести) существующая_ссылка</i>

Таким образом, чтобы передать переменную типа

object
методу
GivePromotion()
, потребуется написать следующий код:

// Правильно!

GivePromotion((Manager)frank);

Использование ключевого слова as

Имейте в виду, что явное приведение оценивается во время выполнения, а не на этапе компиляции. Ради иллюстрации предположим, что проект

Employees
содержит копию класса
Hexagon
, созданного ранее в главе. Для простоты вы можете добавить в текущий проект такой класс:

class Hexagon

{

  public void Draw()

  {

    Console.WriteLine(&quot;Drawing a hexagon!&quot;);

  }

}

Хотя приведение объекта сотрудника к объекту фигуры абсолютно лишено смысла, код вроде показанного ниже скомпилируется без ошибок:

// Привести объект frank к типу Hexagon невозможно,

// но этот код нормально скомпилируется!

object frank = new Manager();

Hexagon hex = (Hexagon)frank;

Тем не менее, вы получите ошибку времени выполнения, или более формально — исключение времени выполнения. В главе 7 будут рассматриваться подробности структурированной обработки исключений, а пока полезно отметить, что при явном приведении можно перехватывать возможные ошибки с применением ключевых слов

try
и
catch
:

// Перехват возможной ошибки приведения.

object frank = new Manager();

Hexagon hex;

try

{

  hex = (Hexagon)frank;

}

catch (InvalidCastException ex)

{

  Console.WriteLine(ex.Message);

}

Очевидно, что показанный пример надуман; в такой ситуации вас никогда не будет беспокоить приведение между указанными типами. Однако предположим, что есть массив элементов

System.Object
, среди которых лишь малая толика содержит объекты, совместимые с
Employee
. В этом случае первым делом желательно определить, совместим ли элемент массива с типом
Employee
, и если да, то лишь тогда выполнить приведение.

Для быстрого определения совместимости одного типа с другим во время выполнения в C# предусмотрено ключевое слово

as
. С помощью ключевого слова
as
можно определить совместимость, проверив возвращаемое значение на предмет
null
. Взгляните на следующий код:

// Использование ключевого слова as для проверки совместимости.

object[] things = new object[4];

things[0] = new Hexagon();

things[1] = false;

things[2] = new Manager();

things[3] = &quot;Last thing&quot;;

foreach (object item in things)

{

  Hexagon h = item as Hexagon;

  if (h == null)

  {

    Console.WriteLine(&quot;Item is not a hexagon&quot;); // item - не Hexagon

  }

  else

  {

    h.Draw();

  }

}

Здесь производится проход в цикле по всем элементам в массиве объектов и проверка каждого из них на совместимость с классом

Hexagon
. Метод
Draw()
вызывается, если (и только если) обнаруживается объект, совместимый с
Hexagon
. В противном случае выводится сообщение о том, что элемент несовместим.

Использование ключевого слова is (обновление в версиях 7.0, 9.0)

В дополнение к ключевому слову

as
язык C# предлагает ключевое слово
is
, предназначенное для определения совместимости типов двух элементов. Тем не менее, в отличие от ключевого слова
as
, если типы не совместимы, тогда ключевое слово
is
возвращает
false
, а не ссылку
null
. В текущий момент метод
GivePromotion()
спроектирован для приема любого возможного типа, производного от
Employee
. Взгляните на следующую его модификацию, в которой теперь осуществляется проверка, какой конкретно "тип сотрудника" был передан:

static void GivePromotion(Employee emp)

{

  Console.WriteLine(&quot;{0} was promoted!&quot;, emp.Name);

  if (emp is SalesPerson)

  {

    Console.WriteLine(&quot;{0} made {1} sale(s)!&quot;, emp.Name,

145
{"b":"847442","o":1}