Na versão 3.0 do C# surgiram as expressões lambda, como uma parte do LINQ. Na prática, elas não passam de funções anônimas, que dispensam a implementação no corpo da classe de operações simples, geralmente com apenas uma instrução.
Concebidas para simplificar e facilitar a codificação das aplicações, até a versão 5.0 do C#, elas eram utilizadas apenas dentro do corpo dos métodos de uma classe. Mas na versão 6.0 foi introduzido um novo recurso chamado Expression-bodied Members.
Curso C# (C Sharp) Básico
Conhecer o cursoEm um passado não muito distante …
O Expression-bodied Members introduzido no C# 6.0 passou a permitir que expressões semelhantes às expressões lambdas fossem utilizadas para definir métodos ou propriedades somente leitura que contenham apenas uma instrução.
Por exemplo, vamos supor uma classe Pessoa
que possua a estrutura abaixo:
public class Pessoa
{
private string nome;
private string sobrenome;
private DateTime dataNascimento;
public string Nome
{
get { return nome; }
set { nome = value; }
}
public string Sobrenome
{
get { return sobrenome; }
set { nome = value; }
}
public DateTime DataNascimento
{
get { return dataNascimento; }
set { dataNascimento = value; }
}
public string NomeCompleto
{
get { return nome + " " + sobrenome; }
}
public int Idade()
{
return (DateTime.Now.Year - dataNascimento.Year - 1) +
(((DateTime.Now.Month > dataNascimento.Month) ||
((DateTime.Now.Month == dataNascimento.Month) &&
(DateTime.Now.Day >= dataNascimento.Day))) ? 1 : 0);
}
}
Com o expression-bodied properties, uma propriedade somente leitura:
public string NomeCompleto
{
get { return nome + " " + sobrenome; }
}
Pode ser alterada para:
public string NomeCompleto => nome + " " + sobrenome;
E com o expression-bodied methods, o método Idade
:
public int Idade()
{
return (DateTime.Now.Year - dataNascimento.Year - 1) +
(((DateTime.Now.Month > dataNascimento.Month) ||
((DateTime.Now.Month == dataNascimento.Month) &&
(DateTime.Now.Day >= dataNascimento.Day))) ? 1 : 0);
}
Pode ser modificado para:
public int Idade() => (DateTime.Now.Year - dataNascimento.Year - 1) +
(((DateTime.Now.Month > dataNascimento.Month) ||
((DateTime.Now.Month == dataNascimento.Month) &&
(DateTime.Now.Day >= dataNascimento.Day))) ? 1 : 0);
É importante frisar que em ambos os exemplos acima os blocos continham return
, mas em um método sem isso:
public void Imprimir()
{
Console.WriteLine(Nome + " " + Sobrenome);
}
Também pode ser aplicado o expression-bodied:
public void Imprimir() => Console.WriteLine(Nome + " " + Sobrenome);
O importante é que o método e propriedade somente leitura contenha uma instrução de uma linha.
Voltando ao presente
Já na versão 7 do C# foram introduzidos mais três recursos ao expression-bodied. Vamos modificar a classe apresentada anteriormente para mostrá-los:
public class Pessoa
{
private string nome;
private string sobrenome;
private DateTime dataNascimento;
public string Nome
{
get { return nome; }
set { nome = value; }
}
public string Sobrenome
{
get { return sobrenome; }
set { nome = value; }
}
public DateTime DataNascimento
{
get { return dataNascimento; }
set { dataNascimento = value; }
}
public string NomeCompleto => nome + " " + sobrenome;
public Pessoa() { }
public Pessoa(string nome)
{
this.nome = nome;
}
~Pessoa()
{
Console.WriteLine("Classe sendo destruída!");
}
public int Idade() => (DateTime.Now.Year - dataNascimento.Year - 1) +
(((DateTime.Now.Month > dataNascimento.Month) ||
((DateTime.Now.Month == dataNascimento.Month) &&
(DateTime.Now.Day >= dataNascimento.Day))) ? 1 : 0);
}
Note que agora temos métodos construtores e o destrutor da classe. E é nesses métodos que a partir da versão 7, pode ser aplicado, respectivamente, o expression-bodied constructors, e o o expression-bodied destructors.
O processo é o mesmo, ambos os métodos precisam conter apenas uma instrução:
public Pessoa(string nome)
{
this.nome = nome;
}
~Pessoa()
{
Console.WriteLine("Classe sendo destruída!");
}
Para expression-bodied ser aplicado:
public Pessoa(string nome) => this.nome = nome;
~Pessoa() => Console.WriteLine("Classe sendo destruída!");
Além do construtor e destrutor, o expression-bodied agora pode ser aplicado aos acessores das propriedades:
public string Nome
{
get => nome;
set => nome = value;
}
Agora que a auto propriedade (disponível desde a versão 2 do C#) ainda é a melhor opção para reduzir código:
public string Nome { get; set; }
Mas, caso seja implementada a interface INotifyPropertyChanged
, o uso deste recurso é bom para reduzir o código:
public string Nome
{
get => nome;
set => SetProperty(ref nome, value);
}
Não tem esse exemplo na classe acima, mas este mesmo princípio que permite o uso do expression-bodied nos acessores das propriedades, pode ser aplicado aos eventos:
private EventHandler _someEvent;
public event EventHandler SomeEvent
{
add => _someEvent += value;
remove => _someEvent -= value;
}
Mas este também tem a sua versão mais simples:
public event EventHandler SomeEvent
Introduzida na versão 6.
Para finalizar, aplicando os conceitos acima à classe Pessoa
, ela ficará com a estrutura abaixo:
public class Pessoa
{
private string nome;
private string sobrenome;
private DateTime dataNascimento;
public string Nome
{
get => nome;
set => SetProperty(ref nome, value);
}
public string Sobrenome
{
get => sobrenome;
set => nome = value;
}
public DateTime DataNascimento
{
get => dataNascimento;
set => dataNascimento = value;
}
public string NomeCompleto => nome + " " + sobrenome;
public Pessoa() { }
public Pessoa(string nome) => this.nome = nome;
~Pessoa() => Console.WriteLine("Classe sendo destruída!");
public int Idade() => (DateTime.Now.Year - dataNascimento.Year - 1) +
(((DateTime.Now.Month > dataNascimento.Month) ||
((DateTime.Now.Month == dataNascimento.Month) &&
(DateTime.Now.Day >= dataNascimento.Day))) ? 1 : 0);
}
Conclusão
Assim como demonstrado com as tuplas, o C# 7.0 está introduzindo recursos que visam melhorar a produtividade dos desenvolvedores, sejam novos, como as já referidas tuplas ou com melhorias de recursos já existentes, como é o caso do expression-bodied.