Employee moonUnit = new Manager("MoonUnit Zappa", 2, 3001, 20000,
"101-11-1321", 1);
GivePromotion(moonUnit);
// PtSalesPerson "является" SalesPerson.
SalesPerson jill = new PtSalesPerson("Jill", 834, 3002, 100000,
"111-12-1119", 90);
GivePromotion(jill);
}
Предыдущий код компилируется благодаря неявному приведению от типа базового класса (Employee
GivePromotion()
с объектом frank
(хранящимся в общей ссылке System.Object
)? Если вы передадите объект frank
методу GivePromotion()
напрямую, то получите ошибку на этапе компиляции:object frank = new Manager("Frank Zappa", 9, 3000, 40000, "111-11-1111", 5);
// Ошибка!
GivePromotion(frank);
Проблема в том, что вы пытаетесь передать переменную, которая объявлена как принадлежащая не к типу Employee
System.Object
. Учитывая, что в цепочке наследования он находится выше, чем Employee
, компилятор не разрешит неявное приведение, стараясь сохранить ваш код насколько возможно безопасным в отношении типов.Несмотря на то что сами вы можете выяснить, что ссылка object
Employee
класса, компилятор сделать подобное не в состоянии, поскольку это не будет известно вплоть до времени выполнения. Чтобы удовлетворить компилятор, понадобится применить Таким образом, чтобы передать переменную типа object
GivePromotion()
, потребуется написать следующий код:// Правильно!
GivePromotion((Manager)frank);
Использование ключевого слова as
Имейте в виду, что явное приведение оценивается
Employees
содержит копию класса Hexagon
, созданного ранее в главе. Для простоты вы можете добавить в текущий проект такой класс:class Hexagon
{
public void Draw()
{
Console.WriteLine("Drawing a hexagon!");
}
}
Хотя приведение объекта сотрудника к объекту фигуры абсолютно лишено смысла, код вроде показанного ниже скомпилируется без ошибок:
// Привести объект frank к типу Hexagon невозможно,
// но этот код нормально скомпилируется!
object frank = new Manager();
Hexagon hex = (Hexagon)frank;
Тем не менее, вы получите ошибку времени выполнения, или более формально —
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();