C#. Passado, presente e futuro

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

Esta publicação está disponível em vídeo, ampliada e revisada, no canal da EximiaCo.


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

10 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.

  5. Vinicius Rocha

    1) O código gerado pelo Source Generator pode ser analisado por outros Source Generators para produzir outros arquivos de código fonte? 2) Será que o Source Generator vai causar dor de cabeça para alguns desenvolvedores no sentido de não conseguir identificar o motivo de a compilação estar tão lenda? “Ah! Você está usando esse source generator aqui que está deixando o processo de compilação mais lenta.” 3) Acho que talvez fosse bom ter na IDE uma opção para visualizar os arquivos gerados em alguma “pasta” no solution explorer. Mesmo que fossem read-only. Ajudaria no problema de on-boarding do projeto.

Deixe uma resposta

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