Novidades do C# 6.0

A versão 2015 do Visual Studio(versão Release Candidate) já está disponível para download e com ele podemos utilizar o novo C# 6.

De acordo com Mads Torgensen, um dos principais responsáveis pelo futuro da linguagem, a ideia geral dessa nova versão é não ter grandes conceitos para você ter que ficar quebrando a cabeça pra aprender. Ao invés disso, focaram em criar pequenas novas funcionalidades pra te ajudar a escrever código melhor e mais limpo.

Vamos dar uma olhada nessas funcionalidades.

Auto-properties só com get

Atualmente, se quisermos criar uma auto-property temos que fazer dessa forma:

public class Conta
{
    public double Saldo { get; set; }
    public int Numero { get; set; }
    public Cliente Titular { get; set; }
}

Mas e se eu quiser que Saldo seja uma propriedade somente leitura(ou seja, sem o set)?
Atualmente, não conseguimos fazer isso com propriedades, teríamos que criar um atributo somente leitura:

public class Conta
{
    public readonly double Saldo;
    public int Numero { get; set; }
    public Cliente Titular { get; set; }
}

No C# 6.0, podemos fazer diferente e definir a propriedade sem o set:

public class Conta
{
    public double Saldo { get; }
    public int Numero { get; set; }
    public Cliente Titular { get; set; }
}

Por trás dos panos, o C# está criando um atributo readonly para nós que, se quisermos, podemos inicializar no construtor da classe:

public class Conta
{
    public double Saldo { get; }
    public int Numero { get; set; }
    public Cliente Titular { get; set; }

    public Conta()
    {
        this.Saldo = 100; //inicializando a conta com o saldo inicial de 100 reais
    }
}

É bom salientar que não estamos usando um setter pra inicializar a propridade, pois não há setter. O C# está colocando o valor 100 direto no atributo readonly que está por trás da propriedade.

Initializers para auto-properties

Podemos também agora inicializar nossas propriedades com um valor padrão:

public class Conta
{
    public double Saldo { get; } = 100;
    public int Numero { get; set; } = 1;
    public Cliente Titular { get; set; } = new Cliente();
}

Isso antes não era possível, se quiséssemos fazer algo parecido tinhamos que inicializar as propriedades no construtor da classe. Veja que isso vale tanto para propriedade com get e set quanto para a que tem só o get.

Using estático

Vamos supor que eu vá fazer várias conversões em minha classe e usarei muito a classe Convert:

public class Conta
{
    public double Saldo { get; } = 100;
    public int Numero { get; set; } = 1;
    public Cliente Titular { get; set; } = new Cliente();
 
    public void Metodo1(string parametro)
    {
        int variavelInt = Convert.ToInt32(parametro);
    }

    public void Metodo2(string parametro)
    {
        double variavelDouble = Convert.ToDouble(parametro);
    }
}

Ao invés de ficar utilizando o nome da classe toda hora, podemos fazer:

using static System.Convert;

public class Conta
{
    public double Saldo { get; } = 100;
    public int Numero { get; set; } = 1;
    public Cliente Titular { get; set; } = new Cliente();
 
    public void Metodo1(string parametro)
    {
        int variavelInt = ToInt32(parametro);
    }

    public void Metodo2(string parametro)
    {
        double variavelDouble = ToDouble(parametro);
    }
}

Veja que colocamos um using direto para a classe, e não para um namespace. Dessa forma podemos chamar os métodos da classe Convert sem termos que ficar colocando o nome da classe toda vez. Detalhe: isso só funciona com classes estáticas.

Interpolação de strings

Suponhamos que eu queira sobrescrever o método ToString em minha classe Conta para que ele retorne o numero e o saldo da conta no formato “Numero:X, Saldo:Y”. Eu poderia fazer dessa forma, usando String.Format:

public class Conta
{
    public double Saldo { get; set; }
    public int Numero { get; set; }
    public Cliente Titular { get; set; }

    public override string ToString()
    {
        return string.Format("Numero:{0}, Saldo:{1}", this.Numero, this.Saldo);
    }
}

Mas esse negócio de usar números dentro de uma string é algo que pode ficar meio confuso dependendo do tamanho dela. Pra simplificar, podemos fazer a mesma coisa, mas agora com uma sintaxe diferente:

public class Conta
{
    public double Saldo { get; set; }
    public int Numero { get; set; }

    public override string ToString()
    {
        return $"Numero:{this.Numero}, Saldo:{this.Saldo}";
    }
}

Note que tiramos a chamada para o método Format e o substituímos por um cifrão($). Fazemos isso para dizer ao C# que estamos fazendo uma interpolação de strings. Dessa forma, ao invés de utilizarmos os placeholders(as chaves) com números, podemos colocar direto os valores que queremos.

Expression-bodied methods para a definição de métodos simples

Esse nosso método ToString() tem só uma linha que retorna um valor, certo? É comum termos vários métodos em nossa aplicação parecidos com esse. Para simplificar a escrita desse tipo de método, agora podemos defini-lo da seguinte forma:

public override string ToString() => $"Numero:{this.Numero}, Saldo:{this.Saldo}";

Podemos utilizar essa síntaxe para propriedades também. Vamos supor que tenhamos uma propriedade chamada ProximoNumero que simplesmente retorna o número da próxima conta:

public class Conta
{
    public double Saldo { get; set; }
    public int Numero { get; set; }

    public int ProximoNumero
    {
         get
         {
             return this.Numero + 1;
         }
    }
}

Podemos simplificar essa propriedade da seguinte forma:

public class Conta
{
    public double Saldo { get; set; }
    public int Numero { get; set; }

    public int ProximoNumero =>  this.Numero + 1;
}

Veja que nessa versão não precisamos colocar o get: ele já está implícito através dessa sintaxe(dessa forma não temos como fazer o get e set).

Operador condicional nulo

Suponhamos que em nosso método ToString(), além de mostrar o número e saldo da conta, queremos também mostrar o nome do titular. Porém, em nossa classe Conta, Titular é uma propriedade do tipo Cliente, que pode ter sido inicializada ou não(estar com o valor null).
Sendo assim teríamos que verificar se se a propriedade é nula, e fazendo isso perderíamos aquela sintaxe simplificada e legal que fizemos para o método:

public class Conta
{
    public double Saldo { get; set; }
    public int Numero { get; set; }
    public Cliente Titular { get; set; } = new Cliente();

    public override string ToString()
    {
        if (this.Titular != null)
        {
            return $"Numero:{this.Numero}, Saldo:{this.Saldo}, Titular:{this.Titular.Nome}";
        }

        else
        {
            return $"Numero:{this.Numero}, Saldo:{this.Saldo}, Titular:";
        }
    }
}

Com o novo operador condicional nulo do C# 6.0, podemos fazer esse método da seguinte forma:

public class Conta
{
    public double Saldo { get; set; }
    public int Numero { get; set; }
    public Cliente Titular { get; set; } = new Cliente();

    public override string ToString() => 
           $"Numero:{this.Numero}, Saldo:{this.Saldo}, Titular:{this.Titular?.Nome}";
}

Repare no ? antes do acesso à propriedade Nome do Titular. Isso significa: tente acessar o Nome do cliente somente se o Titular for diferente de nulo. Se não for, ele simplesmente não acessa. Legal, não? Isso pode evitar vários problemas de referência nula.

Operador nameof

Nós, programadores, lidamos com todo tipo de problema no dia-a-dia. Às vezes, por alguma razão, pode surgir a necessidade de nós sabermos o nome de uma variável e guardarmos ela em uma string. Vamos supor que por alguma razão bizarra queiramos que nossa classe Conta tenha um método que retorne o nome da propriedade Titular. Podemos usar o novo operador nameof:

public class Conta
{
    public double Saldo { get; set; }
    public int Numero { get; set; }
    public Cliente Titular { get; set; } = new Cliente();

    public string RetornaNomeDaPropriedadeTitular()
    {
        return nameof(this.Titular); //retorna "Titular"
    }
}

Conclusão

Como dito no inicio do post, a principal motivação da Microsoft para essa versão do C# são pequenas mudanças que fazem diferença na simplicidade e produtividade. As mudanças aqui realmente parecem pequenas, mas se olharmos do panorama de um grande projeto, elas podem fazer muita diferença na hora de escrever código.

Você pode saber mais sobre as novidades do C# nesse video e nesse post.

E ai, o que você achou das novidades? Deixe seu comentário a respeito!

Você pode aprender C# no curso C# e Orientação a Objetos da Caelum ou através da trilha C# e .NET do Alura.

Tags: ,

35 Comentários

  1. Emílio 19/05/2015 at 09:59 #

    Hahaha! Estou vendo essas influências aí hein Microsoft…

  2. Alberto 19/05/2015 at 10:32 #

    Oi Gabriel, gostei bastante dessa aqui => nameof(this.Titular)

    É possível fazer nameof(Cliente.Titular)? Pergunto porque aí toda vez que você precisar acessar o nome dos atributos da sua classe, fará de maneira type safe. Alguns possíveis exemplos: montar uma query com o nhibernate, names dos inputos dos formulários etc.

  3. Diego 19/05/2015 at 10:42 #

    Bem interessante essa evolução do c#, está o deixando muito interessante de se aprender!

  4. Gabriel Ferreira 19/05/2015 at 10:43 #

    Olá Alberto!

    Seria bem legal, mas infelizmente não dá :/

  5. Felipe 19/05/2015 at 11:03 #

    Estilo das linguagens de Script, tipo Ruby

  6. Gabriel Ferreira 19/05/2015 at 11:15 #

    Fala Emilio! Beleza?

    O using estático é parecido com o do Java, né?
    Que outras influências você viu aí? Conte pra gente (:

  7. Lenon 19/05/2015 at 19:26 #

    Ótimo artigo Gabriel,

    Sobre a “Interpolação de strings”, consigo fazer formatações como no string.Format?

    Ex: string.Format(“CPF: {0:000.000.000-00}”, cpf);

  8. Marcelo 20/05/2015 at 00:22 #

    Esse nameof realmente deixou a desejar…
    nesse caso entao nem vai ser possivel usar para controles databound. mesmo que usando uma instancia, seria inconveniente instanciar um objeto só para pegar o nome de uma propriedade.

    eh.. isso vai ficar pro C# 7

  9. Marcelo 20/05/2015 at 00:26 #

    não entendi a colocaçao do “Auto-properties só com get”
    isso existe desde o C# 2.0.

    Por favor, verifiquem. Quase desisti de ler ao ver essa informação errada.

  10. Marcelo 20/05/2015 at 00:42 #

    Alberto,
    criei uma função para fazer esse trabalho usando reflection.

    veja como ficou o uso:

    Nome = GetPropertyName(c => c.Nome)

    abraços

  11. Gabriel Ferreira 20/05/2015 at 08:35 #

    Oi Lenon!

    Não entendi muito bem o que você quis dizer com esse exemplo, pode ser mais específico por favor?

  12. Gabriel Ferreira 20/05/2015 at 08:39 #

    Oi Marcelo, beleza?
    A informação não está errada, não é possível criar uma propriedade da seguinte forma antes do C# 6:

    public string Propriedade { get; }

    Se você tentar, vai tomar um erro de compilação dizendo que auto-implemented properties precisam definir tanto get quanto o set.
    Acredito que você tenha se confundido e esteja se referindo a outra funcionalidade (:

  13. Lenon 20/05/2015 at 09:44 #

    Gabriel,

    Se eu quero exibir um DateTime formatado da seguinte forma:

    Hoje é dia 20 de maio de 2015.

    Com o string.Format eu faria da seguinte forma:

    string.Format(“Hoje é dia {0:dd} de {0:MMMM} de {0:yyyy}”, DateTime.Now);

    Como eu faria usando a Interpolação de string?

  14. Marcelo 20/05/2015 at 12:15 #

    Verdade, o que era possivel era implementar somente o get

    prop str Teste { get { return _teste; }}

    obrigado pelo esclarecimento

  15. Magno 20/05/2015 at 12:26 #

    Tem os exception filters também:

    http://davefancher.com/2014/08/12/c-6-0-exception-filters/

  16. Gabriel Ferreira 20/05/2015 at 15:52 #

    Oi Lenon, pra esse caso aparentemente não valeria a pela. A interpolação é legal quando você está trabalhando com variáveis.

  17. Steimntz M. de Figueiredo 21/05/2015 at 16:59 #

    Eu usava assim para criar uma propriedade sem set:
    > public string Propriedade { get; private set; }

    Isso funcionava no 3.5.

    Valeu pelo post 🙂

  18. Gabriel Ferreira 21/05/2015 at 17:06 #

    Fala Steimntz!

    Dá pra fazer desse jeito até hoje né? Só que aí a propriedade tem um set, o que significa que podemos alterar o valor da propriedade dentro da classe.
    No exemplo que eu dei, você só pode colocar um valor pra ela no construtor da classe ou direto na declaração – ou seja, readonly (:

    Abraço!

  19. Tiago 26/05/2015 at 10:38 #

    Algumas novidades são bem parecidas com o que vejo no Groovy.

    A interrogação é idêntica ao famoso “elvis”.
    E a interpolação de Strings com o GString com uma sintaxe um pouco diferente.

    Fico feliz que a linguagem está se aprimorando para facilitar o desenvolvedor.

  20. Tiago 26/05/2015 at 10:51 #

    Ato falho.
    Em relação ao Groovy no comentário anterior. Confundi o “elvis” com o “null safe operator”

    http://therealdanvega.com/blog/2013/08/20/groovys-null-safe-operator

  21. Tiago 02/06/2015 at 09:41 #

    M$ copiando linguagens alheias, pelo menos escolheram uns recursos legais.

    Não gostei da questão do static, pois numa equipe inexperiente vai gerar problemas. Na minha opinião, fizeram “caquinha” permitindo isso.

    A questão do auto-property com read only, normalmente faço isso com “private set;”. Entendo que seja read only só para acessos externos, mas funciona muito bem. De qualquer forma, recurso a mais é sempre bom.

  22. Pedro Henrique 02/06/2015 at 09:50 #

    Tiago, já ia falar isso mesmo, na interpolação de strings eu posso usar qualquer comando Java/Groovy dentro do “${}” ou “$”

  23. Diego Koga 02/06/2015 at 11:39 #

    Acho que vc esqueceu de adicionar o using estático no exemplo, ou ele funciona mesmo sem definir o modificador de acesso?

    using System.Convert;
    or
    using static System.Convert;

  24. M. França 02/06/2015 at 14:07 #

    Hey Gabriel, boa tarde.
    O que você quis dizer com “classes estáticas”?
    Abraço,
    França.

  25. Gabriel Ferreira 02/06/2015 at 16:45 #

    @Tiago Normal uma linguagem copiar outra né? Nesse meio dificilmente se cria algo totalmente novo (:
    Com relação ao import estático, o Java já tem há algum tempo e acho um recurso interessante, não vejo problemas.

  26. Gabriel Ferreira 02/06/2015 at 16:54 #

    @Diego Koga
    Faltou o static mesmo, bem observado! Vou corrigir, valeu (:

  27. Gabriel Ferreira 02/06/2015 at 16:57 #

    @M. França
    Conseguimos fazer a “importação” de uma classe com o using estático somente se a classe em questão for estática! (;

  28. Elton 03/06/2015 at 04:17 #

    Ya adorei!!!

  29. Jean Puga 06/06/2015 at 00:06 #

    Legal o C#6, mudanças pequenas e de grandes impactos para muito melhor em nossas linhas .

  30. Fabio Luis Rodrigues 30/12/2015 at 08:43 #

    Como gosto é pessoal, eu particularmente não curto estas novidades no c#, para mim as novidades devem vir no Framework e não na linguagem, pois considero a alteração da linguagem como a criação de uma nova linguagem, se você altera a sintaxe a linguagem deve alterar o nome dela também.

    Não curto muito estas alterações, a Microsoft deveria ter o bom senso de se limitar somente a melhorar o Framework, se necessário alterar a sintaxe de uma linguagem, crie uma nova.

    Como disse é apenas uma opinião acadêmica, sintaxe é sintaxe e não deve mudar.

  31. Gabriel Ferreira 30/12/2015 at 12:01 #

    Olá Fabio!

    Mas a sintaxe da linguagem não mudou, ela continua a mesma. Há apenas novos recursos que você pode escolher utilizar ou não (:

  32. Silvio Delgado 19/02/2016 at 11:31 #

    Gostei muito das alterações.
    Com certeza vieram para facilitar a vida de quem codifica, sem comprometer a legibilidade de código e, acredito eu, melhorando o desempenho (até porque, muita gente já fazia isso aí com algumas gambiarras sinistras! rsrs).

    Em relação a “copiar outras linguagens”, sim, certamente isso foi feito (o PHP, por exemplo, já possui algumas propriedades dessas). Mas que mal há nisso? O que acontece é uma convergência para a melhor forma (falando de forma generalizada) de programar. E não há mal nenhum nisso.
    Quem não gostar, tem, simplesmente, a opção de não utilizar os recursos.
    Boa, Microsoft! Muito obrigado.
    (E muito obrigado ao Gabriel pelo post).

  33. Wedson 10/05/2016 at 13:58 #

    Gabriel, excelente artigo, didática fantástica!! Parabéns!

    O bacana em tudo isso é que a linguagem está evoluindo, copiando ou não, ela está avançando e sempre para melhor. Da mesma forma como ela já foi copiada, não há problema nenhum em incorporar o que há de melhor, mesmo que já exista na concorrência, isso só demonstra que a principal preocupação é com o cliente que utiliza a plataforma: se é bom e pode agregar, vamos então vamos incorporar!

    Sou um desenvolvedor preguiçoso, logo, quanto mais recursos para fazer mais com menos existir, melhor….

    Realmente faltou mencionar sobre Exceptions Filters, Métodos Incorporados e também do Dictionary Initializer…

    Os operadores condicionais nulos foram uma sacada genial, vão reduzir bastante código bem como os famosos NullPointExceptions da vida!

    A MS sempre surpreendendo a todos com suas novidades voltadas a quem desenvolve e entrega soluções…..

  34. BitoCambuta 27/10/2016 at 20:05 #

    olá parabens pelo post…
    eu gostaria de saber se até a data de hoje(27/10/2016) está é a vesão mais recente do Visual Studio…
    obrigado

  35. Gabriel Ferreira 28/10/2016 at 11:25 #

    BitoCambuta, a versão mais recente do Visual Studio você pode encontrar aqui https://www.visualstudio.com/vs/community/ 🙂

Deixe uma resposta