C#. Passado, presente e futuro

Em breve C# terá suporte para metaprogramação: códigos melhores com custo muito mais baixo

As próximas versões do compilador da linguagem C# irão fornecer, finalmente, suporte a metaprogramação. Trata-se de uma novidade importante que vai permitir, em diversos cenários, ganhos consideráveis de produtividade no desenvolvimento e de performance na execução das aplicações.

O suporte a metaprogramação será oferecido através de uma nova feature até então conhecida como Source Generators.

Source Generators

Um Source Generator é um código escrito para ser executado durante o processo de compilação e que consegue “inspecionar” o programa sendo compilado, produzindo artefatos adicionais para serem compilados junto.

Trata-se de um novo tipo de componente que desenvolvedores conseguem produzir permitindo:

  1. Obter um objeto Compilation com todas as informações sobre o código que está sendo compilado. Este objeto pode ser inspecionado e permite que sejam produzidos artefatos considerando a sintaxe e modelos semânticos.
  2. Gerar código C# para ser adicionado ao objeto Compilation. Em outras palavras, é possível adicionar código-fonte extra como input para o processo de compilação que está sendo executado.

Quando combinadas, essas duas capacidades se mostram realmente úteis. Podemos inspecionar o código fonte sendo compilado, com informações ricas obtidas durante a compilação para, então, gerar código novo.

— Blog da Microsoft sobre Source Generators

Um Source Generator é uma classe simples, escrita por qualquer programador, que será instanciada e executada automaticamente durante o processo da compilação.

Uma versão em preview do Visual Studio já integra a execução dos source generators com a escrita do código tornando a experiência fluída.

public class CsvLineGenerator : ISourceGenerator
{
    public void Execute(SourceGeneratorContext context)
    {
        throw new NotImplementedException();
    }

    public void Initialize(InitializationContext context)
    {
        throw new NotImplementedException();
    }
}

Com source generators será possível, por exemplo, escrever funcionalidades similares aos Type Providers do F#, acelerando o desenvolvimento pela geração automática de tipos, por exemplo, a partir de arquivos CSV, JSON, XML e HTML, reduzindo, significativamente, tanto custos de desenvolvimento quanto de manutenção.

Muito do código que hoje é escrito de forma manual e repetitiva poderá ser gerado automaticamente a partir de “pistas” deixadas pelos desenvolvedores no código. Um exemplo, extraído da página de referência da funcionalidade, que demonstra bem esse cenário, é a escrita de código para implementar a interface INotifyPropertyChanged.

using AutoNotify;

public partial class UserClass
{
    [AutoNotify]
    private bool _boolProp;

    [AutoNotify(PropertyName = "Count")]
    private int _intProp;
}

No exemplo, bastará o programador utilize um atributo como “pista” para que um source generator, durante o processo de compilação, escreva o código apropriado.

public partial class UserClass : INotifyPropertyChanged
{
    public bool BoolProp
    {
        get => _boolProp;
        set
        {
            _boolProp = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("UserBool"));
        }
    }

    public int Count
    {
        get => _intProp;
        set
        {
            _intProp = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

As vantagens evidentes incluem, obviamente, menos código explicitamente escrito pelos programadors no dia a dia, bem como garantias de implementação de comportamento padrão que reduz, inclusive, a necessidade de escritas de testes.

Source Generators seguramente também irão reduzir a necessidade de reflection, que, embora seja um recurso extremamente poderoso, tem custo extremamente elevado em runtime.

Bem implementados, source generators podem gerar grande economia. Entretanto, será importante atentar para o risco de uso demasiado que pode aumentar as dificuldades para gestão dos times – afinal, será necessário capacitar as pessoas para, além de entender o domínio, entender quais source generators são adotados e em que situações.

A funcionalidade está ainda em preview e deverá estar disponível, junto com C# 9, até o final de 2020.

Em Resumo
  • O fato

    A partir do final de 2020 o compilador de C# oferecerá suporte a metaprogramação através de "source generators".
  • Os benefícios

    Source generators tem potencial para quase eliminar a escrita de código repetitivo, melhorar a padronização e, eventualmente, reduzir a demanda de testes de unidade. Além disso, podem trazer para tempo de compilação determinados desafios hoje resolvidos em tempo de execução com reflection, melhorando a performance.
  • Ponto de atenção

    O uso não disciplinado da nova funcionalidade pode tornar o código, embora menor, mais difícil de entender.

Elemar Júnior

Microsoft Regional Director e Microsoft MVP. Atua, há mais de duas décadas, desenvolvendo software e negócios digitais de classe mundial. Teve o privilégio de ajudar a mudar a forma como o Brasil vende, projeta e produz móveis através de software. Hoje, seus interesses técnicos são arquiteturas escaláveis. bancos de dados e ferramentas de integração. Além disso, é fascinado por estratégia e organizações exponenciais.

Talvez você goste também

Carregando posts…

Mais posts da série C#. Passado, presente e futuro

9 Comentários
  1. TIAGO A ESMERALDINO

    Só não entendo como eu referencio uma property que só existe em tempo de compilação no meu código “normal”. Ele sabe o que vai ser gerado e não da erros? Vc testou como funciona isso?

    1. Elemar Júnior

      No Visual Studio 2019 Preview, ele roda os Source Generators na mesma lógica dos Code Analyzers. Então, o código fonte novo é gerado e considerado enquanto você escreve o código.

      1. TIAGO A ESMERALDINO

        Nossa que legal, muito muito show.

  2. ISMAEL GASPARIN

    Como fica a questão do debugging e breakpoints?

    1. Elemar Júnior

      Até agora, debugging e breakpoints para código local funciona plenamente. Código gerado pelos Source Generators, até onde vi, é tratado com código externo.

  3. Gustavo Aquino

    Elemar, isso não se compara a algumas características que o CodeDOM permite fazer no .NET Framework?

    1. Elemar Júnior

      Não. A ideia aqui é permitir mudar os executáveis durante a compilação.

  4. Michel B Souza

    Daria para dizer que o Source Generators atuaria como uma espécie de delegate?

    1. Elemar Júnior

      Não. Delegates apontam para uma função, determinada assinatura, para ser executada. Source Generators é código que roda durante o processo de compilação.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *