Extension methods são uma das minhas funcionalidades preferidas que o C# pode oferecer. Claro que com os anos a Microsoft tem lançados muitas melhorias na linguagem, mas extension methods exitem já ha muitos anos, desde a versão 3.0, e são muito uteis.
Estes métodos são uma forma de extender a funcionalidade de qualquer tipo de dados ou classe, mesmo que nativos, mas que funcionam como métodos nativos. Para mim, uma das grandes vantagens é mesmo a forma limpa como podemos escrever código e fazer com que o código fique mais fácil de ler e de compreender.
Como um exemplo simples vamos imaginar que queremos agarrar numa string e remover todos os espaços que possam existir na string.
Claro que facilmente poderia ser utilizado o método replace e substituir todos espaços por nada.
var stringComEspacos = "teste para remover espaços";
var stringSemEspacos = stringComEspacos.Replace(" ", "");
Assim tinhamos o problema resolvido, mas a nível de leitura do código para quem está a ler pela primeira vez aquele replace poderá fazer confusão ou até achar que está ali a faltar alguma coisa. Para evitar confusão, poderíamos criar uma função chamada RemoveSpaces e passar a string a remover os espaços. Desta forma forma fica claro o objetivo de fazer o replace, e vamos ser sinceros, não interessa saber como é que os espaços são removidos, o importante é perceber que o resultado daquela string é a própria string sem os espaços.
public string RemoveSpaces(string stringComEspacos)
{
return stringComEspacos.Replace(" ", "");
}
Com esta função ficaríamos com o seguinte código, que até parece bem:
var stringComEspacos = "teste para remover espaços";
var stringSemEspacos = RemoveSpaces(stringComEspacos);
Agora não há confusão sobre o que a função está a fazer. Ainda assim, acredito que o código poderia ficar um pouco melhor e é aqui que entra o exthension method. No fundo para tornar a nossa função removespaces num extension method basta incluir a palavra this no argumento. Um nota importante é que o this no argumento apenas pode ser utilizado em métodos estáticos, portanto entre public e string também coloquei static. Abaixo deixo o método completo.
public static class ExtensionMethods
{
public static string RemoveSpaces(this string stringComEspacos)
{
return stringComEspacos.Replace(" ", "");
}
}
Com esta alteração o código ficaria assim:
var stringComEspacos = "teste para remover espaços";
var stringSemEspacos = stringComEspacos.RemoveSpaces();
Resumindo, com o this estamos a dizer que o é para passar como argumento o próprio objecto que vem antes da chamada da função. Neste caso o stringcomescos é passado como argumento automaticamente.
Claro que aqui estamos a ver um exemplo simples, mas é possível extender os métodos para qualquer tipo de dados sejam primitivos, objectos complexos ou até mesmo um objecto de uma API externa. Estes métodos não estão limitados a apenas um argumento, podemos ter múltiplos argumentos, contudo apenas um pode conter o this. Os restantes argumentos são passados entre os parêntesis da chamada da função. Um exemplo com funcções poderia ser um método para efectuar uma soma de dois números:
public static int Add(this int a, int b)
{
return a + b;
}
var cinco = 5;
var sete = cinco.Add(2);
Utilizo regularmente extension methods, muitas vezes para criar metodos específicos sobre outros tipos de dados a que não tenho acesso à classe para definir novos métodos. O que costumo fazer, num projecto de maior dimensão, é criar uma classe para cada tipo de dados diferente. Nestes dois exemplos teria uma classe chamada StringHelper ou StringExtensionMethod e uma outra de IntHelper ou IntExtenstionMethod. Podes ainda encontrar mais informação e outros exemplos diferentes diretamente na documentação da microsoft. Se nunca experimentaste, desafio-te a criar o teu primeiro extension method, num projeto que estejas a desenvolver.