Pattern matching

Паттерн типов

Последнее обновление: 07.01.2022

Pattern matching фактически выполняет сопоставление некоторого значения с некоторым шаблоном. И если сопоставление прошло успешно, то выполняются определенные действия. Язык C# позволяет выполнять различные типы сопоставлений.

Паттерн типов или type pattern позволяет проверить некоторое значение на соответствие некоторому типу:

значение is тип переменная_типа

Например, у нас есть следующие классы:

class Employee
{
    public virtual void Work() => Console.WriteLine("Employee works");
}

class Manager : Employee
{
    public override void Work() => Console.WriteLine("Manager works");
    public bool IsOnVacation { get; set; }
}

Класс Employee представляет работника, а класс Manager - менеджера. Оба класса реализуют метод Work. Кроме того, класс Manager определяет свойство IsOnVacation.

С помощью паттерна типов проверим, представляет ли объект Employee класс Manager:

Employee tom = new Manager();
UseEmployee(tom);	// Manager works

void UseEmployee(Employee emp)
{
    if (emp is Manager manager && manager.IsOnVacation == false)
    {
        manager.Work();
    }
    else
    {
        Console.WriteLine("Преобразование не допустимо");
    }
}

Здесь в методе UseEmployee значение emp сопоставляется с типом Manager. То есть в данном случае в качестве шаблона выступает тип Manager. Если сопоставление прошло успешно (то есть значение emp представляет тип Manager), в переменной manager оказывается объект emp. И далее мы можем вызвать у него методы и свойства.

Также мы можем использовать constant pattern - сопоставление с некоторой константой:

var message = "hello";

// проверяем, соответствует ли значение message строке "hello"
if (message is "hello")
{
   Console.WriteLine("hello");
}

Подобным образом, например, можно проверить значение на null:

Employee? bob = new Employee();
Employee? tom = null;

UseEmployee(bob);
UseEmployee(tom);

void UseEmployee(Employee? emp)
{
    if (emp is not null)
        emp.Work();
}

Кроме конструкции if сопоставление паттернов может применяться в конструкции switch:

Employee bob = new Employee();
Employee tom = new Manager();
UseEmployee(tom);   // Manager works
UseEmployee(bob);   // Object is not manager

void UseEmployee(Employee? emp)
{
    switch (emp)
    {
        case Manager manager:
            manager.Work();
            break;
        case null:
            Console.WriteLine("Object is null");
            break;
        default:
            Console.WriteLine("Object is not manager");
            break;
    }
}

С помощью выражения when можно вводить дополнительные условия в конструкцию case:

Employee bob = new Manager() { IsOnVacation = true };
Employee tom = new Manager() { IsOnVacation = false };
UseEmployee(tom);   // Manager works
UseEmployee(bob);   // Employee does not work

void UseEmployee(Employee? emp)
{
    switch (emp)
    {
        case Manager manager when !manager.IsOnVacation:
            manager.Work();
            break;
        case null:
            Console.WriteLine("Employee is null");
            break;
        default:
            Console.WriteLine("Employee does not work");
            break;
    }
}

В этом случае опять же преобразуем объект emp в объект типа Manager и в случае удачного преобразования смотрим на значение свойства IsOnVacation: если оно равно false, то выполняется данный блок case.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850