{
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
{...}
В мире .NET Core каждый тип в конечном итоге является производным от базового класса по имени
System.Object
, который в языке C# может быть представлен с помощью ключевого слова
object
(с буквой
о
в нижнем регистре). Класс
Object
определяет набор общих членов для каждого типа внутри платформы. По сути, когда вы строите класс, в котором явно не указан родительский класс, компилятор автоматически делает его производным от
Object
. Если вы хотите прояснить свои намерения, то можете определять классы, производные от
Object
, следующим образом (однако вы не обязаны поступать так):
// Явное наследование класса от System.Object.
class Car : object
{...}
Подобно любому классу в
System.Object
определен набор членов. В показанном ниже формальном определении C# обратите внимание, что некоторые члены объявлены как
virtual
, указывая на возможность их переопределения в подклассах, тогда как другие помечены ключевым словом
static
(и потому вызываются на уровне класса):
public class Object
{
<b> // Виртуальные члены.</b>
public virtual bool Equals(object obj);
protected virtual void Finalize();
public virtual int GetHashCode();
public virtual string ToString();
<b> // Невиртуальные члены уровня экземпляра.</b>
public Type GetType();
protected object MemberwiseClone();
<b> // Статические члены.</b>
public static bool Equals(object objA, object objB);
public static bool ReferenceEquals(object objA, object objB);
}
В табл. 6.1 приведен обзор функциональности, предоставляемой некоторыми часто используемыми методами
System.Object
.