No dia 04/12 aconteceu o Microsoft Connect(); 2018, com transmissões online abordando novidades de tecnologias como .NET, C#, Visual Studio e o Microsoft Azure.
No caso específico do C# 8.0, tivemos a disponibilização de uma versão para testes, juntamente com o Preview 1 do Visual Studio 2019 e do .NET Core 3. Maiores informações a respeito da instalação destes releases podem ser encontradas no seguinte artigo:
Esse artigo inicia uma série que publicarei cobrindo as principais novidades do C# 8.0. Neste primeiro momento demonstrarei como habilitar essa versão (ainda Beta) no Visual Studio 2019, bem como o uso de Indices e Ranges na manipulação de arrays (tais funcionalidades também se estendem a construções como strings e Span).
Criando o projeto para testes
A IDE do Visual Studio 2019 Preview 1 passou por algumas mudanças, sendo que talvez uma das diferenças mais visíveis esteja no processo de criação de novos projetos. Na janela a seguir foi selecionado o template Console App (.NET Core):
Já no próximo formulário, deverá ser especificado o nome e o caminho para a criação do projeto:
Habilitando o uso do C# 8.0 no Visual Studio 2019
O exemplo apresentado neste artigo foi implementado a partir do Visual Studio 2019 Preview 1. É importante destacar que releases anteriores não contam com suporte para a versão 8.0 da linguagem C#.
Caso o uso do C# 8.0 não tenha sido previamente habilitado, alertas (destacados em vermelho), aparecerão no Visual Studio 2019 ao tentar se empregar algum dos novos recursos:
Para evitar esse tipo de problema, será necessário alterar as propriedades do projeto em questão. Na seção Build, acionar a opção Advanced…:
Em Language version, selecionar então C# 8.0 (beta) ou C# latest minor version (latest), a fim de ativar os recursos desta nova versão da linguagem:
Ranges e Indices
Conforme mencionado anteriormente, Ranges e Indices são elementos concebidos com o objetivo de facilitar a manipulação de construções como arrays, strings e representações baseadas em Span.
Considerando o exemplo da listagem a seguir, temos:
- Um array com seis posições contendo strings que se referem a diversas tecnologias;
- A instrução tecnologias[2..5] faz uso de índices para selecionar um range de elementos que vai da segunda posição até a quarta do array tecnologias (o limite da segunda parte do range é exclusivo. Logo, será considerada a posição imediatamente anterior – neste caso, 4).
using System;
namespace ExemploRangesIndices
{
class Program
{
static void Main(string[] args)
{
string[] tecnologias =
new string[] { ".NET Core", "Angular", "ASP.NET Core", "Azure", "C#", "Docker" };
Console.Write("Retornando elementos dos índices 2 a 4: [");
foreach (string tecnologia in tecnologias[2..5])
{
Console.Write($" *{tecnologia}*");
}
Console.Write(" ]" + Environment.NewLine);
Console.ReadKey();
}
}
}
A seguir está o resultado da execução deste código:
Podemos refatorar esse código declarando uma variável baseada no struct Range (namespace System) que contenha os índices com o intervalo de elementos desejados. É o que demonstra a próxima listagem:
using System;
namespace ExemploRangesIndices
{
class Program
{
static void Main(string[] args)
{
string[] tecnologias =
new string[] { ".NET Core", "Angular", "ASP.NET Core", "Azure", "C#", "Docker" };
Range range = 2..5;
Console.Write("Retornando elementos dos índices 2 a 4 via struct Range: [");
foreach (string tecnologia in tecnologias[range])
{
Console.Write($" *{tecnologia}*");
}
Console.Write(" ]" + Environment.NewLine);
Console.ReadKey();
}
}
}
Como resultado, teremos:
Índices e Ranges também podem ser empregados na passagem de parâmetros a um método, por exemplo.
Na próxima listagem temos casos que retomam os dois testes anteriores, além de outras possibilidades de uso destes novos recursos:
- Uma expressão como ..5 selecionará o elemento de posição zero (ao se omitir tal valor foi assumido justamente 0 como default) até o quarto elemento do array;
- Já a utilização de ^ permite a seleção até um determinado ponto considerado a partir do término do array. Dessa forma, ^1 permite que se retorne até o penúltimo item do array, ao passo que ^2 fará o mesmo com o antepenúltimo elemento.
using System;
namespace ExemploRangesIndices
{
class Program
{
static void Main(string[] args)
{
string[] tecnologias =
new string[] { ".NET Core", "Angular", "ASP.NET Core", "Azure", "C#", "Docker" };
ImprimirElementos(tecnologias[2..5],
"Retornando elementos dos índices 2 a 4");
Range range = 2..5;
ImprimirElementos(tecnologias[range],
"Retornando elementos dos índices 2 a 4 via struct Range");
ImprimirElementos(tecnologias[0..5],
"Retornando elementos dos índices 0 a 4");
ImprimirElementos(tecnologias[..5],
"Retornando até o elemento de posição 4 (desde a posição 0)");
ImprimirElementos(tecnologias[1..^2],
"Retornando elementos da posição 1 até o antepenúltimo");
ImprimirElementos(tecnologias[1..^1],
"Retornando elementos da posição 1 até o penúltimo");
ImprimirElementos(tecnologias[..^1],
"Retornando até o penúltimo elemento");
Console.ReadKey();
}
private static void ImprimirElementos(string[] selecaoTecnologias,
string mensagem)
{
Console.Write($"{mensagem}: [");
foreach (string tecnologia in selecaoTecnologias)
{
Console.Write($" *{tecnologia}*");
}
Console.Write(" ]" + Environment.NewLine);
}
}
}
Ao executar este novo bloco de instruções, o resultado será o seguinte: