Expandindo C#: mitos e verdades sobre extension properties

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Extension Properties em C#: quando você quer, mas não pode (e como contornar)



Imagine a situação: você trabalha com uma biblioteca onde a classe Person tem a propriedade FullName. Tudo ótimo, mas eis o problema — você precisa adicionar uma propriedade calculada AgeInDays, que calcula a idade em dias a partir da data de nascimento. Você está acostumado com extension methods (métodos de extensão) e pensa: "Por que não criar extension properties (propriedades de extensão)?"



E então você vai ao Stack Overflow, vê uma pergunta com milhares de visualizações: "Does C# have extension properties?" — e lê a resposta com decepção: "Não, não são oficialmente suportadas". Mas não feche a aba ainda! Neste artigo, não apenas entenderemos por que elas não existem, mas também encontraremos soluções elegantes que não perdem em desempenho.



Por que o C# não adiciona extension properties? Contexto histórico



Vamos começar pelo principal: extension properties não são um capricho, mas um pedido antigo da comunidade. Ainda em 2016, uma proposta (C# feature request) apareceu no GitHub, mas até hoje não foi implementada. Por quê?



  • Complexidade com o compilador: Diferente dos métodos, as propriedades têm getters e setters que precisam estar vinculados a uma instância específica. Estender essa lógica no nível de sintaxe exige mudanças significativas no compilador.
  • Conflito com indexadores: Propriedades e indexadores em C# são intimamente relacionados. Adicionar extension properties poderia criar ambiguidades.
  • Prioridade de outros recursos: A equipe do C# focou em records, pattern matching e static abstract members (C# 11), que trazem mais benefícios para a maioria dos cenários.


Mas a falta de suporte oficial não é uma sentença. Vamos ver como desenvolvedores experientes resolvem esse problema.



Métodos de extensão: sua principal ferramenta (mas com nuances)



A maneira mais óbvia é usar extension methods em vez de propriedades. Em vez de person.AgeInDays, você escreve person.GetAgeInDays(). Isso funciona, mas quebra o princípio de uniformidade: no resto do código você usa propriedades, e aqui, de repente, um método.



public static class PersonExtensions{    public static int GetAgeInDays(this Person person)    {        return (DateTime.Now - person.BirthDate).Days;    }}

// Uso:var age = person.GetAgeInDays(); // Funciona, mas não é bonito


Desvantagem: o código se torna menos legível, especialmente em cadeias de chamadas LINQ. Vantagem: é totalmente gratuito em termos de desempenho — a chamada de um método de extensão não difere de um método estático comum.



Alternativa nº 1: Fábricas estáticas e classes auxiliares



Se você precisa de uma "propriedade" que é calculada com base em dados, pode criar uma classe auxiliar estática:



public static class PersonHelper{    public static int AgeInDays(Person person) => (DateTime.Now - person.BirthDate).Days;}

// Uso:var age = PersonHelper.AgeInDays(person);


Isso é mais honesto que um método de extensão: fica claro que é uma função auxiliar. Mas ainda não é uma propriedade.



Alternativa nº 2: Atributos e geração de código (Source Generators)



Para cenários complexos (por exemplo, adicionar propriedades a classes de pacotes NuGet), você pode usar source generators. Eles surgiram no .NET 5 e permitem gerar código em tempo de compilação. Você escreve um atributo, e o gerador cria uma classe parcial com as propriedades desejadas.



[AutoExtensionProperty(typeof(Person), nameof(Person.BirthDate))]public partial class PersonExtensions{    // O gerador criará a propriedade AgeInDays}

// Código gerado:public partial class PersonExt

Blogs

Book Recommendations