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

12/13/2016 23:40:00 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.

O que há de novo no C# 7.0 - Literais binários

09/06/2016 23:11:00 By Felipe Pessoto

Além dos números decimais e hexadecimais, no C# 7.0 é possível escrever usando notação binária:

class BinaryLiteral
{
    public static void Example()
    {
        int myValue = 0b1010;
    }
}

Facilitando muito a criação de Flags Enum:

public enum MyFlagsEnumCSharp60
{
    None = 0,
    Sunday = 1,
    Monday = 2,
    Tuesday = 4,
    Wednesday = 8,
    Thursday = 16,
    Friday = 32,
    Saturday = 64
}

public enum MyFlagsEnum2CSharp60
{
    None = 0,
    Sunday = 1,             // 1
    Monday = 1 << 1,        // 2
    Tuesday = 1 << 2,       // 4
    Wednesday = 1 << 3,     // 8
    Thursday = 1 << 4,      // 16
    Friday = 1 << 5,        // 32
    Saturday = 1 << 6,      // 64
}

public enum MyFlagsEnumCSharp70
{
    None =      0b00000000,
    Sunday =    0b00000001,
    Monday =    0b00000010,
    Tuesday =   0b00000100,
    Wednesday = 0b00001000,
    Thursday =  0b00010000,
    Friday =    0b00100000,
    Saturday =  0b01000000
}

O que há de novo no C# 7.0 - Separador de dígitos

09/06/2016 23:04:00 By Felipe Pessoto

Uma pequena mas util nova funcionalidade é a possibilidade de utilizar separadores entre os dígitos, facilitando a leitura. Por exemplo:

class DigitSeparator
{
    public const int MyValue = 123_456;
    public const int MyHexValue = 0xAB_CD_EF;

    public static void Example()
    {
        Console.WriteLine(MyValue);
        Console.WriteLine(MyHexValue);
    }
}

Não há nenhuma diferença no código compilado com ou sem os separadores.

O que há de novo no C# 7.0 - Variáveis Out

08/28/2016 13:39:00 By Felipe Pessoto

Até o C# 6.0, chamar um método que utiliza parâmetros out não é tão fluido, pois você precisa declarar as variáveis antes de chamar o método, e nem é possível usar o var já que normalmente não se inicializa variáveis que são argumentos do método out.

Então você precisa verificar quais os tipos das variaveis utilizadas nos parametros out, voltar e declarar antes do método:

public void OutVariablesExample60()
{
    int myX;//var myX doesn't work
    int myY;

    if(MethodOut(out myX, out myY))
    {
        Console.WriteLine(myX);
    }
}

No C# 7.0 esta experiência será melhorada, ao chamar o método você pode declarar as variáveis de forma inline. Com isso o compilador sabe os tipos delas, permitindo inclusive o uso do var:

public void OutVariablesExample70()
{
    if (MethodOut(out int myX, out var myY))
    {
        Console.WriteLine(myX);
    }
}

As variáveis declaradas estarão no escopo do bloco onde o método é chamado. No Preview 4 o compilador ainda restinge o escopo para o statement onde a variável foi declarada, por isso só funciona como no exemplo acima, onde temos um bloco IF. Esta restrição será removida até a versão final.

Sempre que novas funcionalidades são acrescentadas acho interessante verificar como o código IL é gerado para saber como foi feita a implementação. Neste caso é bem simples, o novo código gera uma versão identica ao exemplo em C# 6.0.