Tecnologias
- Framework 3.5
- C# 3.0
MSDN
- Extension Methods (C# Programming Guid)
- How to: Implement and Call a Custom Extension Method (C# Programming Guide)
Conversando com alguns colegas de trabalho sobre os Extension Methdos do C# 3.0, tivemos uma discussão sobre a padronização da utilização desse
recurso e quando utilizar ou não o mesmo.
Os Extension Methods permitem que o
desenvolvedor adicione métodos a um determinado tipo sem a necessidade
de alterar o código fonte original ou criar tipos derivados. Os métodos
que são adicionados têm as mesmas características de um método
estático, porém a utilização dos mesmos funciona como se eles fossem
métodos de instância. Esse recurso foi largamente utilizado para
disponibilizar os métodos que trabalham com LINQ na versão mais recente do framework .net.
Definição
A definição é relativamente simples, para criar um extension method siga os seguintes passos:
- Crie um arquivo de código.
- Defina uma classe estática.
- A classe deve estar em um namespace acessível para os clientes.
- Defina
um método estático com o primeiro argumento sendo do tipo que você
pretende estender, antes do tipo adicione a palavra this. - Escreva o corpo do método.
Ao final, você terá algo semelhante à imagem 01:

Imagem 01
Como podem ver na linha 1, defini que minha classe ficaria no namespace System. Fiz isso por que a classe String também está nesse namespace. Logo, quem estiver usando a classe também terá acesso ao método ToInt32.
Na linha 3 defini a classe StringExtensions como sendo pública e estática. Você pode usar o nome que quiser para a classe.
Dica
Eu adotei um padrão
onde o nome da classe estática fica sendo sempre o tipo que estou
estendendo seguido da palavra Extensions.
Na linha 5 declarei o método estático ToInt32, vocês podem reparar que a grande diferença aqui é a utilização da palavra this antes do primeiro parâmetro do método. O método tem que ter no mínimo um parâmetro sendo do tipo que você pretende estender.
Vejam como ficou a utilização do método na imagem 02:

Imagem 02
Como vimos, a utilização do método fica bem prática, como se o mesmo fosse de instância, e não estático.
Quando utilizar?
Apesar de ser um método estático, o mesmo será
utilizado como um método de instância, logo, o ideal é utilizar esse
recurso quando faça sentido que o método seja utilizado assim.
Vale a pena utilizar esse recurso, pois a sintaxe fica bem mais limpa do que um método utilitário normal.

Imagem 03
A imagem 03 possibilita a comparação entre a utilização convencional e da utilização do extension method.
Dica
Métodos auxiliares
nem sempre são bons candidatos a serem extension methods, exemplos de
métodos que não deveriam utilizar esse recurso: FormatarCpf(),
FormatarCnpj(), EhEmailValido(). Nesses casos, continue utilizando os
métodos estáticos convencionais no padrão de assistente.
Organização dos arquivos
A organização dos arquivos é um ponto crucial para trabalhar em projetos com vários desenvolvedores. Quando usamos extensions
podemos confundir o time de desenvolvimento, já que os métodos não ficam
junto com a definição do tipo, logo, use um padrão que fique bem
explícito que o projeto usa esse recurso.

Imagem 04
A imagem 04 mostra como organizei os arquivos do projeto de exemplo. Notem que existe uma pasta específica para Extensions,
onde ficam os métodos para tipos do sistema, como string, int, etc. No
caso da interface IPessoa, seus métodos ficam em um arquivo de mesmo
nome com sufixo .sufixo.
Dica
Defina o padrão que
atende melhor as necessidades do projeto e da equipe de
desenvolvimento, a regra não é usar o padrão que estou usando, mas sim
usar um padrão que todos os envolvidos no projeto entendam.
Mixin
Um efeito colateral bom da inserção dos extension
methods é o fato de o desenvolvedor poder adicionar comportamentos a
interfaces, esses comportamentos por sua vez poderão ser utilizados em
todos os tipos que implementam a interface. As próximas imagens
ilustram o cenário:

Imagem 05

Imagem 06

Imagem 07
Como podem ver, declarei uma interface IPessoa e duas classes que implementam a mesma. Adicionei um Extension Method à interface IPessoa e depois pude utilizar o método nos tipos que implementam a interface.
Veja mais sobre mixin.
Espero que tenham gostado e aguardo feedbacks.
Abraços,
Denis Ferrari
Download do projeto de exemplo.
Qual a sua opinião?