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

  {

    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
.

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