Dando continuidade a nossa série de posts sobre os novos recursos do C# 9.0. No artigo passado vimos as propriedades init e records (registros) e agora conheceremos mais dois: programas top-level e as melhorias do pattern matching.
Programas Top-level
Antes da versão 9.0, para escrever qualquer código no C# era necessário declarar ao menos uma classe, com um método Main
estático. Como no famoso “Hello World” abaixo:
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World");
}
}
Quem nunca viu um código na vida, pode ter dificuldade em compreender todos os conceitos utilizados no código acima. Para ajudar nisso, no C# 9.0 foi introduzido os programas top-level, que não necessitam de classe nem do método Main
para serem executados.
Com os programas top-level, o famoso “Hello World” pode ser definido da seguinte forma:
using System;
Console.WriteLine("Hello World");
Qualquer expressão válida do C# pode ser declarada em um programa top-level, com a limitação que isso só pode ser definido em um arquivo de código. Mesmo que o programa declare uma função:
using System;
int Soma(int var1, int var2) {
return var1 + var2;
}
Console.WriteLine(Soma(10, 20));
Ela só pode ser utilizada dentro do arquivo onde foi criada. Será gerado um erro se for invocada fora dele.
Também é importante ressaltar que os usings sempre devem ser as instruções iniciais do código. Caso estiverem no meio dele, será gerado um erro.
Por fim, os programas top-level definem a variável global args
, que contém os argumentos passados via linha de comando e podem retornar um valor para o sistema operacional:
using static System.Console;
WriteLine(args[0]);
return 0;
O valor retornado indica se o programa finalizou com sucesso ou não. Lembrando que qualquer valor diferente de zero indica que o programa foi finalizado devido a um erro.
Melhorias no pattern matching
O pattern matching foi introduzido no C# 7.0 como uma forma de facilitar a verificação do tipo de dado de uma variável. Na versão 8.0, com a introdução das Switch Expressions este recurso recebeu suas primeiras melhorias e agora na nona versão, novos recursos foram incorporados ao padrão.
Antes, quando o pattern matching é aplicado em uma switch expression:
public double CustoObra(object item)
{
return item switch
{
Formato t when t.Area < 100 => Area * 1.8,
Formato t when t.Area > 200 => Area * 1.5,
Formato _ => Area * 2.0,
};
}
Era necessário informar um identificador, mesmo que fosse descartado (_
), agora isso não é necessário:
public double CustoObra(object item)
{
return item switch
{
Formato t when t.Area < 100 => Area * 1.8,
Formato t when t.Area > 200 => Area * 1.5,
Formato => Area * 2.0,
};
}
Quando se está aplicando condições a mesma propriedade como no exemplo acima, podemos utilizar o relational pattern e utilizar apenas os condicionais no switch:
public double CustoObra(Formato item)
=> Formato t when t.Area switch
{
< 100 => Area * 1.8,
> 200 => Area * 1.5,
_ => Area * 2.0,
};
Que também pode receber os operadores lógicos or
, and
e not
:
public double CustoObra(Formato item)
=> Formato t when t.Area switch
{
> 0 and <= 100 => Area * 1.8,
> 100 and <= 200 => Area * 1.6,
> 200 => Area * 1.5,
_ => Area * 2.0,
};
Sempre que possível, opte pelo operador not
, em detrimento de !
, já que o primeiro melhora a legibilidade do código. Ele pode ser utilizado para verificar se um valor não é nulo:
public Formato SelecionarFormato(object item)
=> item switch
{
FormatoPlanta.Quadrado => new Quadrado(Largura, Altura),
FormatoPlanta.Retangulo => new Retangulo(Largura, Altura),
FormatoPlanta.Triangulo => new Triangulo(Largura, Altura, 2),
not null => throw new ArgumentException("Formato desconhecido"),
null => throw new ArgumentNullException(nameof(item))
};
Ou mesmo para analisar o tipo de uma variável:
if (item is not FormatoPlanta) { throw ... }
Ao aplicar um condicional como o acima, o C# saberá o tipo da variável, então o compilador aceita algo assim:
if (item is not FormatoPlanta) { throw ... }
var = item.Area ...
Com isso finalizamos mais um artigo sobre o C# 9.0. No próximo abordarei outros recursos desta nova versão da linguagem. Até lá!