Язык программирования C#9 и платформа .NET5
Несмотря на то что сами вы можете выяснить, что ссылка
указывает в памяти на объект совместимого сobjectкласса, компилятор сделать подобное не в состоянии, поскольку это не будет известно вплоть до времени выполнения. Чтобы удовлетворить компилятор, понадобится применить явное приведение, которое и является вторым правилом: в таких случаях вы можете явно приводить "вниз", используя операцию приведения С#. Базовый шаблон, которому нужно следовать при выполнении явного приведения, выглядит так:Employee<i>(класс_к_которому_нужно_привести) существующая_ссылка</i>Таким образом, чтобы передать переменную типа
методуobject, потребуется написать следующий код:GivePromotion()// Правильно!GivePromotion((Manager)frank);Использование ключевого слова as
Имейте в виду, что явное приведение оценивается во время выполнения, а не на этапе компиляции. Ради иллюстрации предположим, что проект
содержит копию классаEmployees, созданного ранее в главе. Для простоты вы можете добавить в текущий проект такой класс:Hexagonclass Hexagon{public void Draw(){Console.WriteLine("Drawing a hexagon!");}}Хотя приведение объекта сотрудника к объекту фигуры абсолютно лишено смысла, код вроде показанного ниже скомпилируется без ошибок:
// Привести объект 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] = "Last thing";foreach (object item in things){Hexagon h = item as Hexagon;if (h == null){Console.WriteLine("Item is not a hexagon"); // item - не Hexagon}else{h.Draw();}}Здесь производится проход в цикле по всем элементам в массиве объектов и проверка каждого из них на совместимость с классом
. МетодHexagonвызывается, если (и только если) обнаруживается объект, совместимый сDraw(). В противном случае выводится сообщение о том, что элемент несовместим.HexagonИспользование ключевого слова is (обновление в версиях 7.0, 9.0)
В дополнение к ключевому слову
язык C# предлагает ключевое словоas, предназначенное для определения совместимости типов двух элементов. Тем не менее, в отличие от ключевого словаis, если типы не совместимы, тогда ключевое словоasвозвращаетis, а не ссылкуfalse. В текущий момент методnullспроектирован для приема любого возможного типа, производного отGivePromotion(). Взгляните на следующую его модификацию, в которой теперь осуществляется проверка, какой конкретно "тип сотрудника" был передан:Employeestatic void GivePromotion(Employee emp){Console.WriteLine("{0} was promoted!", emp.Name);if (emp is SalesPerson){Console.WriteLine("{0} made {1} sale(s)!", emp.Name,