Такое условие будет давать совпадение с чем угодно, а потому следует уделять внимание порядку, в котором используется блок сравнения с отбрасыванием. Ниже показан обновленный метод GivePromotion():
if (emp is SalesPerson s)
{
Console.WriteLine("{0} made {1} sale(s)!", s.Name, s.SalesNumber);
Console.WriteLine();
}
// Если Manager, тогда присвоить переменной m
else if (emp is Manager m)
{
Console.WriteLine("{0} had {1} stock options...", m.Name, m.StockOptions);
Console.WriteLine();
}
else if (emp is var _)
{
// Некорректный тип сотрудника
Console.WriteLine("Unable to promote {0}. Wrong employee type", emp.Name);
Console.WriteLine();
}
Финальный оператор if будет перехватывать любой экземпляр Employee, не являющийся Manager, SalesPerson или PtSalesPerson. Не забывайте, что вы можете приводить вниз к базовому классу, поэтому PtSalesPerson будет регистрироваться как SalesPerson.
Еще раз о сопоставлении с образцом (нововведение в версии 7.0)
В главе 3 было представлено средство сопоставления с образцом C# 7.0 наряду с его обновлениями в версии C# 9.0. Теперь, когда вы обрели прочное понимание приведения, наступило время для более удачного примера. Предыдущий пример можно модернизировать для применения оператора switch, сопоставляющего с образцом:
static void GivePromotion(Employee emp)
{
Console.WriteLine("{0} was promoted!", emp.Name);
switch (emp)
{
case SalesPerson s:
Console.WriteLine("{0} made {1} sale(s)!", emp.Name,
s.SalesNumber);
break;
case Manager m:
Console.WriteLine("{0} had {1} stock options...",
emp.Name, m.StockOptions);
break;
}
Console.WriteLine();
}
Когда к оператору case добавляется конструкция when, для использования доступно полное определение объекта SalesNumber существует только в классе SalesPerson, но не в классе Employee. Если приведение в первом операторе case проходит успешно, то переменная s будет содержать экземпляр класса SalesPerson, так что оператор case можно было бы переписать следующим образом:
case SalesPerson s when s.SalesNumber > 5:
Такие новые добавления к is и switch обеспечивают удобные улучшения, которые помогают сократить объем кода, выполняющего сопоставление, как демонстрировалось в предшествующих примерах.
Использование отбрасывания вместе с операторами switch (нововведение в версии 7.0)
Отбрасывание также может применяться в операторах switch:
switch (emp)
{
case SalesPerson s when s.SalesNumber > 5:
Console.WriteLine("{0} made {1} sale(s)!", emp.Name,
s.SalesNumber);
break;
case Manager m:
Console.WriteLine("{0} had {1} stock options...",
emp.Name, m.StockOptions);
break;
case Employee _:
// Некорректный тип сотрудника
Console.WriteLine("Unable to promote {0}. Wrong employee type", emp.Name);
break;
}
Каждый входной тип уже является Employee и потому финальный оператор case всегда дает true. Однако, как было показано при представлении сопоставления с образцом в главе 3, после сопоставления оператор switch завершает работу Это демонстрирует важность правильности порядка. Если финальный оператор case переместить в начало, тогда никто из сотрудников не получит повышения.
Главный родительский класс: System.Object
В заключение мы займемся исследованием главного родительского класса Object. При чтении предыдущих разделов вы могли заметить, что базовые классы во всех иерархиях (Car, Shape, Employee) никогда явно не указывали свои родительские классы:
// Какой класс является родительским для Car?
class Car
{...}