O que há de novo no C# 7.0 - Pattern Matching

12/14/2016 2:40:00 AM By Felipe Pessoto

Pattern Matching é uma nova estrutura na linguagem que permite testar um valor contra um determinado formato enquanto atribui seu resultado.

Na versão 7.0 do C# são esperados três patterns:

  • Constant - Testa a expressão contra uma constante, isto é, literais, variável const, o valor de um enum ou typeof
  • Type - Testa se uma expressão é de um determinado tipo e em caso de sucesso faz o cast para o tipo, atribuindo o resultado em uma variável
  • Var - Esta expressão sempre é executada com sucesso, servindo apenas para atribuir o valor em uma nova variável

E mais estão por vir, no GitHub é possível ler o documento sobre Pattern Matching

Atualmente estes patterns podem ser utilizados nas expressões is e no case do bloco switch.

Is Expressions

 O principal uso nas expressões is será do Type Pattern, para atribuir uma variavel enquanto teste seu tipo. Por exemplo, quando é necessário executar um método de uma classe derivada, em vez de:

Dog dog = animal as Dog;
if(dog != null)
{
    dog.Bark();
}

//Ou

if (animal is Dog)
{
    Dog dog = (Dog)animal;
    dog.Bark();
}

É possível validar e atribuir em uma unica expressão:

if (animal is Dog dog)
{
    dog.Bark();
}

Como muitos dos recursos são apenas Syntactic Sugar, recomendo sempre avaliar qual a IL gerada, neste caso, é equivalente ao seguinte código C#:

Dog dog;
if ((dog = (animal as Dog)) != null)
{
    dog.Bark();
}

 Switch statements

 Com o switch fica ainda mais interessante ao combinar as condições, mantendo as regras separadas para cada caso e o código mais claro:

Animal animal = GetAnimal();

switch (animal)
{
    case Dog dog when dog.IsShortHaired:
        Console.WriteLine("Short Haired");
        break;
    case Dog dog:
        Console.WriteLine("Not Short Haired");
        break;
    case Cat cat:
        Console.WriteLine("Cat");
        break;
    case null:
        throw new ArgumentNullException();
    default:
        Console.WriteLine("Animal");
        break;
}

 O escopo de cada variavel atribuida no case é restrita ao bloco em que foi declarado e pode ser utilizado para validar outras regras, como no exemplo o IsShortHaired. Assim caso alguma validação não seja feita com sucesso, o bloco não é executado e o próximo case é avaliado.

Outra mudança importante é que agora o ordem dos case's é validada na compilação, impedindo que se use um case que inutilize os que estão abaixo dele, por exemplo:

E o case default será sempre executado por último, não importando o local em que foi declarado.


Comments (0)