André Alves de Lima

Talking about Software Development and more…

Outras novidades do C# vNext

Olá caro(a) leitor(a)!

Nos meus últimos dois artigos, eu abordei duas novidades da próxima versão do C#. No primeiro deles, expliquei como a utilização de parâmetros de saída (out) fica muito mais simples com a chegada da funcionalidade de “Declaration Expressions” no C# vNext. Já no segundo artigo, detalhei como os “Primary Constructors” da próxima versão do C# ajudam bastante a nossa vida e possibilitam removermos grande parte do código dos construtores das nossas classes. Como mencionei no artigo anterior, essas novas funcionalidades foram anunciadas no evento Microsoft Build 2014, que foi realizado algumas semanas atrás.

Mas, essas não são as únicas novidades da próxima versão do C#. Muitas outras melhorias já foram implementadas e outras estão por vir. Porém, na minha humilde opinião, nenhuma dessas outras melhorias é digna de um artigo somente para ela. Portanto, resolvi abordar rapidamente todas essas outras novas funcionalidades neste último artigo dessa série. Então, vamos lá.

Inicializadores em auto-properties

Vocês sabem o que são auto-properties? Não? Pois bem, auto-properties são aquelas propriedades que não têm corpo definido e somente contém o “get; set;” vazios. Por exemplo, as propriedades Nome e Sobrenome no código abaixo:

    class Pessoa
    {
        public string Nome { get; set; }
        public string Sobrenome { get; set; }
    }

Na versão atual do C#, se quisermos definir um valor inicial para auto-properties, temos que definir esse valor no construtor da classe:

    class Pessoa
    {
        public string Nome { get; set; }
        public string Sobrenome { get; set; }
        public Pessoa()
        {
            Nome = "Fulano";
            Sobrenome = "de Tal";
        }
    }

A novidade é que na próxima versão do C#, não precisamos mais definir esses valores no construtor, porque podemos defini-los diretamente na frente da declaração das auto-properties:

    class Pessoa
    {
        public string Nome { get; set; } = "Fulano";
        public string Sobrenome { get; set; } = "de Tal";
    }

E você já tentou criar uma auto-property que tivesse somente “get“? Obviamente isso não é permitido, porque se a propriedade é somente “get“, nunca conseguiríamos associar um valor para ela. Na versão atual do C#, ao tentarmos criar uma auto-property somente com “get“, recebemos o seguinte erro:

‘XXX.get’ must declare a body because it is not marked abstract or extern. Automatically implemented properties must define both get and set accessors.

Já na próxima versão do compilador do C#, ao tentarmos criar uma auto-property que só tenha “get“, recebemos uma mensagem de erro diferente:

Auto-implemented properties must have set accessors or initializers.

Perceberam a diferença? Na versão atual, o compilador simplesmente nos informa que auto-properties precisam definir ambos “get” e “set“. Ponto final. Já a mensagem de erro do compilador do C# vNext é um pouco diferente: auto-properties precisam definir “set” ou devem ser inicializadas. Isso quer dizer que agora podemos ter auto-properties que só tenham “get“, desde que inicializemos a propriedade:

    class Pessoa
    {
        public string Nome { get; } = "Fulano";
        public string Sobrenome { get; set; }
    }

Meio inútil, já que nunca conseguiremos alterar o valor dessa propriedade, fazendo com que ela seja praticamente uma constante no final das contas. Mas, enfim, fica aí a informação de que isso agora é possível de ser feito.

Using com tipos

Essa funcionalidade permite que nós especifiquemos tipos em cláusulas using, de forma que os métodos estáticos fiquem acessíveis sem que tenhamos que digitar o nome da classe. Por exemplo, veja este código de uma console application que simplesmente imprime a frase “Hello world” no console:

using System;

namespace MyConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello world");
        }
    }
}

Notem que temos uma cláusula using para o namespaceSystem“, por isso conseguimos acessar a classe Console (que está dentro do namespaceSystem“) e então acessar o seu método estático WriteLine para imprimir a frase no console.

Agora, imaginem que pudéssemos definir um using para a própria classe “System.Console“. Dessa forma, poderíamos acessar o método WriteLine diretamente. Isso é o que conseguimos fazer na próxima versão do C#:

using System.Console;

namespace MyConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            WriteLine("Hello world");
        }
    }
}

Não sei até onde isso é bom ou ruim. Imagine a confusão que isso pode trazer se importarmos classes que têm métodos com o mesmo nome? E depois pra saber qual método está vindo de qual classe? Enfim, de qualquer forma fiquem atentos, porque essa funcionalidade está para vir no C# vNext.

Exception filters

Agora temos a possibilidade de adicionar uma cláusula “if” logo após cláusula “catch“. Dessa forma podemos avaliar uma condição e decidir se trataremos ou não a exceção:

            try
            {
                // Alguma coisa...
            }
            // Tratamos a exceção somente se o dicionário "Data" da exceção tiver a key "SomeKey".
            // Caso contrário, a exceção é propagada.
            catch (Exception ex) if (ex.Data.Contains("SomeKey"))
            {
            }

Bem direto, não? Não me vejo utilizando muito essa funcionalidade, mas, de qualquer forma, fica documentado aqui.

Binary literals e separadores de dígitos

Agora poderemos definir valores para bits de forma literal, ao invés de termos que utilizar o int correspondente. Nada de mais:

var bits = b001;

Essa funcionalidade ainda não está implementada no preview atual, mas, deve vir junto com a versão final. Outra pequena funcionalidade que ainda não está implementada no preview, mas que deve sair na versão final é a possibilidade de utilizarmos separadores em dígitos. Imaginem que queremos associar o valor “um milhão, novecentos e oitenta e três mil, setecentos e cinquenta e seis” a uma variável decimal. Na próxima versão do compilador C#, poderemos utilizar underlines (_) para separarmos blocos em valores numéricos. Dessa forma, para deixarmos o valor mais compreensível, poderemos separar os milhões dos milhares e os milhares das centenas:

decimal valorMuitoGrande = 1_983_756;

Membros e inicializadores indexados

Essa nada mais é do que outra maneira de inicializar coleções de key/value pairs. Atualmente, podemos inicializar esse tipo de coleção da seguinte maneira:

            var posicoes = new System.Collections.Generic.Dictionary<int, string> 
            {
                { 10, "Decimo lugar" },
                { 20, "Vigésimo lugar" }
            };

Na próxima versão do C#, teremos outra opção para inicializar essas coleções. Vejam só:

            var posicoes = new System.Collections.Generic.Dictionary<int, string>
            {
                [10] = "Decimo lugar",
                [20] = "Vigésimo lugar"
            };

Além disso, se a chave dessas coleções for do tipo string, temos ainda outra opção para inicializar, associar e recuperar os valores dos itens:

            // Inicializando.
            var valores = new System.Collections.Generic.Dictionary<string, object>
            {
                $nome = "Fulano",
                $sobrenome = "de Tal"
            };

            // Associando um novo valor.
            valores.$nome = "Ciclano";

            // Acessando os valores.
            Console.WriteLine("{0} {1}", valores.$nome, valores.$sobrenome);

Await em blocos catch e finally

Nada muito interessante. Isso é algo que simplesmente estava faltando e agora o time resolveu implementar. Basicamente agora podemos utilizar await em blocos catch e finally, algo que não é possível na versão atual do C#. Com isso, podemos implementar algo do tipo:

        private async Task SomeMethod()
        {
            Pessoa pessoa = new Pessoa();

            try
            {
                await pessoa.SalvarAsync();
            }
            catch (Exception ex)
            {
                await pessoa.LogarErroAsync(ex);
            }
            finally
            {
                await pessoa.FinalizarPessoaAsync();
            }
        }

 

E com isso concluo a lista das principais novidades da próxima versão do C#. Caso vocês queiram acompanhar em tempo real quais features já estão implementadas e quais estão por vir, confiram a lista completa neste link.

Até a próxima!

André Lima

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *