C# - Apresentando Expression Bodied Member


Neste artigo vou apresentar o novo recurso Expression Bodied Member introduzido na versão 6.0 e incrementado na versão 7.0 da linguagem C#.

Mas afinal o que vem a ser Expression Bodied Member (daqui em diante vou identifica como EBM) ?

Na versão 6.0 a linguagem C# permitiu a implementação de propriedades somente leitura e métodos através das expressões lambdas e isso foi chamado de EBM.

Na versão 7.0 a linguagem C# incrementou esse recuso permitindo a utlização de expressões lambdas em construtores, propriedades com get/set e finalizadores.

O objetivo do recurso e tornar o código consciso e legível fazendo com que o membro do tipo (construtor, métodos, propriedades, destrutor, etc) seja definido em uma única expressão.

A sintaxe é :    membro => expressão

onde:

Vejamos a seguir exemplos de utilização do recurso em cada um dos tipos possíveis.

Recursos Usados:

1 - Construtor

O recurso EBM pode ser definido em um construtor usando uma única instrução.

Para isso se o construtor deve possuir uma única expressão válida que pode ser uma atribuição ou uma chamada de método.

Se o construtor possuir mais de uma linha de código ou expressão não podemos usar o EBM.

Exemplo:

using static System.Console;
namespace ExpressionBodiedMember
{
    class Calculadora
    {
        public int Numero1 = 100;
        public int Numero2 = 33;
        // A expressão tem que ser uma expressão válida
        // Podemos usar atribuição, invocação, incremento, decremento e uma nova expressão
        // Só funciona no C# 7.0 ou superior ou seja no  Visual Studio 2017 ou superior
        public Calculadora() => Numero1 = Numero1 + Numero2;
    }
    class Program
    {
        static void Main(string[] args)
        {
            // Cria um a instância da classe
            Calculadora ops = new Calculadora();
            ReadLine();
        }
    }
}

O código acima usa o recurso EBM no construtor. Lembrando que :

Outras possibilidades seriam:

public Calculadora() => WriteLine("O valor de Numero1 é " + Numero1 + " e de Numero2 é : " + Numero2);

public Calculadora() => Numero1 = Numero1 + (100 * Numero2) / 2;

2 - Método

Podemos usar o recurso EBM para definir um método em uma única instrução. Se o tipo de retorno do método não for void o EMB deve retornar o tipo de retorno do método.

Exemplo:

using static System.Console;
namespace EBM_Metodo
{
    class Calculadora
    {
        // Exibe um texto no console
        public void Exibir() => WriteLine("Olá, Macoratti");
        // Invoca outro método
        public void Invocar() => Exibir();
        // Possui dois parâmetros e retorna a soma mais 100
        // Não precisa usar Return com EBM
        public int Somar(int a, int b) => a + b + 100;
        // Método tem dois parâmetros e retorna um valor de acordo
        // com a condição do operador ternário
        public int Comparar(int a, int b) => a == b ? 100 : 200;
    }
    class Program
    {
        static void Main(string[] args)
        {
            Calculadora calc = new Calculadora();
            calc.Exibir();
            calc.Invocar();
            calc.Somar(135, 243);
            calc.Comparar(13,12 );
            ReadLine();
        }
    }
}

No código acima o corpo da expressão é usado com o método.

A seguir alguns exemplos inválidos:

 //declaração não pode ser usada
public void Invocado() => int k;



//ocorre um erro "Invalid expression term 'int'"
public int Somar(int a, int b) => int c=a+b;



//ocorre um erro "Invalid expression term 'return'"
public int Comparar(int a, int b) => return a == b? 100 : 200;

3 - Propriedade get

Podemos definir um acessor get usando EBM.  A palavra-chave return não é necessária.

using static System.Console;
namespace ExpressionBodiedMember
{
    class Calculadora
    {
        public int Numero1 = 100;
        public int Numero2 = 33;
        public string Nome
        {
            get => Nome;
        }
        public Calculadora() => Numero1 = Numero1 + Numero2;
    }
    class Program
    {
        static void Main(string[] args)
        {
            // Cria um a instância da classe
            Calculadora ops = new Calculadora();
            ReadLine();
        }
    }
}

4 - Propriedade set

A expressão deverá atribuir um valor de retorno para a variável do tipo de dados definido na propriedade

using static System.Console;
namespace ExpressionBodiedMember
{
    class Calculadora
    {
        public int Numero1 = 100;
        public int Numero2 = 33;
       public string Nome
      {
            get => Nome;
            set => Nome = value;  
      }  
        public Calculadora() => Numero1 = Numero1 + Numero2;
    }
    class Program
    {
        static void Main(string[] args)
        {
            // Cria um a instância da classe
            Calculadora ops = new Calculadora();
            ReadLine();
        }
    }
}

5 - Indexadores

A EBM pode ser usada para definir os acessores de index get e set.

using static System.Console;
namespace EBM_Indexadore
{
      class Calculadora
       {
            public int Numero1 = 100;
            public int Numero2 = 33;
            public string[] Nomes = new string[5];
            public string this[int i]
            {
                get => Nomes[i];
                set => Nomes[i] = value;
            }
        public Calculadora() => Numero1 = Numero1 + Numero2;
        }
        class Program
        {
            static void Main(string[] args)
            {
                // Cria um a instância da classe
                Calculadora ops = new Calculadora();
                ReadLine();
            }
       }
}

Resumindo:

- Um EBM pode ser public, protected, internal, private, e protected internal;
- Os EBM podem ser declarados virtuais ou abstratos.
- Um EBM pode até substituir um método de classe base.
- Os EBM podem ser estáticos.
- Os EBM requerem apenas uma declaração como expressão.
- Os EBM não suportam Loop (For, while, do while etc.), mas eles podem ser substituídos por uma expressão LINQ.
- Os EBM não suportam declarações condicionais (if-else, if-else aninhado, switch, etc), mas o if-else pode ser substituído pelo operador ternário.
 

"E disse-lhes: Ide por todo omundo, pregai o evangelho a toda criatura. Quem crer e for batizado será salvo; mas quem não crer será condenado."
Marcos 16:15,16

Referências:


José Carlos Macoratti