Pattern de tipuri
Pattern matching efectuează de fapt potrivirea unei valori cu un anumit șablon. Și dacă potrivirea a avut succes, se execută anumite acțiuni. Limbajul C# permite efectuarea diferitelor tipuri de potriviri.
Patternul de tip sau type pattern permite verificarea unei valori pentru a corespunde unui anumit tip:
valoare is tip variabilă_tip
De exemplu, avem următoarele clase:
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; }
}
Clasa Employee reprezintă un angajat, iar clasa Manager - un manager. Ambele clase implementează metoda Work. În plus, clasa Manager definește proprietatea IsOnVacation.
Cu ajutorul patternului de tip verificăm dacă obiectul Employee reprezintă clasa 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("Conversia nu este permisă");
}
}
Aici, în metoda UseEmployee, valoarea emp este potrivită cu tipul Manager. Deci, în acest caz, tipul Manager acționează ca un șablon. Dacă potrivirea a avut succes (adică valoarea emp reprezintă tipul Manager), variabila manager conține obiectul emp. Și mai departe putem apela metodele și proprietățile acestuia.
De asemenea, putem folosi constant pattern - potrivirea cu o anumită constantă:
var message = "hello";
// verificăm dacă valoarea message corespunde șirului "hello"
if (message is "hello")
{
Console.WriteLine("hello");
}
În mod similar, putem verifica valoarea pentru null:
Employee? bob = new Employee();
Employee? tom = null;
UseEmployee(bob);
UseEmployee(tom);
void UseEmployee(Employee? emp)
{
if (emp is not null)
emp.Work();
}
Pe lângă construcția if, potrivirea patternurilor poate fi aplicată în construcția 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;
}
}
Cu ajutorul expresiei when putem introduce condiții suplimentare în construcția 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;
}
}
În acest caz, transformăm din nou obiectul emp într-un obiect de tip Manager, iar în cazul unei conversii reușite, verificăm valoarea proprietății IsOnVacation: dacă este false, se execută acest bloc case.