domingo, 5 de outubro de 2008

Interfaces e Extension Methods: uma combinação poderosa (parte 1)

Dividi esse post em três partes para que quem estiver vendo ExtensionMethods pela primeira vez possa digerir e aplicar a informação para que se siga para a segunda e terceira parte.

A primeira parte (esse post) explica os coneitos básicos de Extension Methods.

A segunda parte (que vou terminar de escrever ao longo da semana) vai procurar mostrar como implementar um modelo de validação de controles distintos através de interfaces comuns com extension methods.

A terceira parte (que pretendo escrever em breve) vai mostrar a importância do uso de extension methods com interfaces na arquitetura do linq. Procurando dissecar a estratégia usada na classe IQueryable.

Extension Methods (Vamos lá!)

Se eu pudesse enumerar um motivo para não deixar o C# 3.0 por qualquer versão anterior no .net, esse motivo seria Extension Methods. Definitivamente!

Extension Methods é uma maneira muito elegante de incorporar em classes métodos que não são própriamente da classe, mas sim de uma classe de "extensão".

Para escrever extension Methods, devemos ter em mente algumas regrinhas básicas:

  • Extension Methods devem contidos em classes estáticas, ou seja, uma classe que contenha apenas membros estáticos.
  • Assim, não é difícil concluir que Extension Methods são métodos estáticos. :-P
  • Pela natureza dessa funcionalidade, há possibilidade de colisão de identificadores, então, o compilador C# adota padrões de precedência.

Pois bem, para quem nunca viu um Extension Method, funciona da seguinte forma:

Se imagine no C# 2.0, onde você tem sua função "CpfValido" que faz a verificação de um CPF a partir de uma string de entrada e retorna bool (true se o CPF for válido):

string cpf = "822.232.339-99";
...

if ( MinhaClasse.EhCpf(cpf) ){
//código válido...
}

Confesse! :-) O que você realmente gostaria de usar seria:

string cpf = "822.232.339-99";
...

if ( cpf.EhCpf() ){
//código válido...
}


mas afinal, isso era impossível! EhCpf não é um método da classe string, e sim de uma classe utilitária que não tem nenhuma relação de herança com a classe string. E até esse ponto (C# 2.0) não há nenhuma forma de produzir tal efeito se não fosse através de mecanismos de herança (e no caso da classe string, que é selada, nem isso! Então como fica?). Mas o panorama mudou no C# 3.0...

na sua classe utilitária, que era algo do tipo:

namespace MeuNamespace{

public static class MinhaClasse{

public static bool EhCpf(string cpf){
//Trata se eh CPF

}

}


}

Agora fica:


namespace MeuNamespace{

public static class MinhaClasse{

public static bool EhCpf(this string cpf){
//Trata se eh CPF

}

}


}
Só isso! Agora sua classe "MinhaClasse" pode ser usada como um extension method da classe string. Mas para isso, você deve referenciar o namespace com a clausula using no contexto do código, como descrito no exemplo.

Nenhum comentário: