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.