Back-End

27 dez, 2018

Novidades do C# 8.0: como habilitar, Ranges e Indices

Publicidade

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:

Referências