.NET

24 jun, 2019

Novidades do C# 8.0: Default Interface Members

100 visualizações
Publicidade

Este último mês de Maio/2019 foi bastante agitado dentro da comunidade .NET, com o anúncio de novos updates do Visual Studio 2019 e do .NET Core 3.0. Com essas novas versões um dos recursos mais esperados para o C# 8.0 também foi disponibilizado para testes: Default Interface Members.

Permitindo agora que implementações de métodos e propriedades sejam declaradas em uma interface, esta nova funcionalidade contribui para evitar a quebra de código quando da necessidade de inclusão de novos membros nessas estruturas.

Na listagem a seguir temos um exemplo envolvendo a interface IPrestadorServico, além das classes PessoaFisica e PessoaJuridica como duas possíveis implementações da mesma:

namespace ExemploDefaultInterfaceMembers
{
    public interface IPrestadorServico
    {
        string Codigo { get; }
        string Nome { get; set; }
    }

    public class PessoaFisica : IPrestadorServico
    {
        public string CPF { get; set; }
        public string Codigo { get => CPF; }
        public string Nome { get; set; }
    }

    public class PessoaJuridica : IPrestadorServico
    {
        public string CNPJ { get; set; }
        public string Codigo { get => CNPJ; }
        public string Nome { get; set; }
    }
}

Podemos testar o uso de Default Interface Members com as estruturas aqui apresentadas como exemplo por meio das seguintes alterações:

  • Declarando a propriedade PossuiCNPJ em IPrestadorServico e atribuindo como valor default true. Esta mesma propriedade pode ainda ser redefinida em PessoaFisica para retornar false, ao passo que nenhuma alteração acontecerá em PessoaJuridica;
  • Com o método ObterDescricaoGeral, sem que se efetuem modificações em PessoaFisica e PessoaJuridica.
namespace ExemploDefaultInterfaceMembers
{
    public interface IPrestadorServico
    {
        string Codigo { get; }
        string Nome { get; set; }
        bool PossuiCNPJ { get => true; }

        string ObterDescricaoGeral()
        {
            return $"{Codigo}, {Nome}, é uma Empresa: " +
                (PossuiCNPJ ? "Sim" : "Não");
        }
    }

    public class PessoaFisica : IPrestadorServico
    {
        public string CPF { get; set; }
        public string Codigo { get => CPF; }
        public string Nome { get; set; }
        public bool PossuiCNPJ { get => false; }
    }

    public class PessoaJuridica : IPrestadorServico
    {
        public string CNPJ { get; set; }
        public string Codigo { get => CNPJ; }
        public string Nome { get; set; }
    }
}

É importante destacar que membros com implementação default e que não foram redefinidos nas classes que derivam de uma interface não estarão disponíveis para acesso direto. O que isso significa na prática para este último exemplo?

Com uma referência baseada em PessoaFisica ou PessoaJuridica não estará disponível o método ObterDescricaoGeral. Variáveis declaradas como sendo do tipo IPrestadorServico terão acesso a tal método.

Já a propriedade PossuiCNPJ estará disponível apenas para variáveis declaradas como sendo da classe PessoaFisica ou baseadas na interface IPrestadorServico. Esta propriedade não estará disponível para acesso direto via referência do tipo PessoaJuridica.

Na imagem a seguir estão ilustrados esses pontos:

A próxima listagem traz um exemplo de utilização dos tipos PessoaFisica e PessoaJuridica em uma Console Application, com o método ImprimirDadosPrestador recebendo como parâmetro referências baseadas nestas classes:

using System;

namespace ExemploDefaultInterfaceMembers
{
    class Program
    {
        private static void ImprimirDadosPrestador(
            IPrestadorServico prestador)
        {
            Console.WriteLine(prestador.ObterDescricaoGeral());
        }

        static void Main()
        {
            var pessoaFisica = new PessoaFisica();
            pessoaFisica.CPF = "22222222222";
            pessoaFisica.Nome = "Testando Pessoa Física";
            ImprimirDadosPrestador(pessoaFisica);
            
            var pessoaJuridica = new PessoaJuridica();
            pessoaJuridica.CNPJ = "33444555777788";
            pessoaJuridica.Nome = "TestePessoaJuridica";
            ImprimirDadosPrestador(pessoaJuridica);
        }
    }
}

A seguir está o resultado da execução deste projeto:

Caso queira saber mais a respeito de outras novidades que integram o C# 8.0acesse o post a seguir, em que agrupo todos os conteúdos que venho produzindo sobre esta versão:

C# 8.0 – Guia de Referência: artigos, vídeos e exemplos de utilização

E também a gravação de uma apresentação recente no Canal .NET, em que o MVP André Secco e eu apresentamos em detalhes as novidades do C# 8.0: