segunda-feira, 24 de março de 2014

Extension Methods em C#

Introdução

Já alguma vez teve necessidade de adicionar métodos a classes de que não possuía o código-fonte?

Neste artigo vamos ver o que são os Extension Methods e como podemos usá-los no Microsoft .NET C#.

Esta é uma das melhores características que foram introduzidas no .NET, em termos de legibilidade do código. Vamos ver o que são os métodos de extensão, como criá-los e também alguns exemplos de aplicação prática.

Conteúdo

O que são Extension Methods

Os métodos de extensão permitem estender facilmente um tipo (como integer ou string), sem criar um novo tipo derivado, recompilar ou de alguma forma modificar o tipo original.

Os métodos de extensão são um tipo especial de métodos estáticos (static), mas são chamados como se fosse métodos de instância do tipo original. Para o código cliente, escrito em C# ou Visual Basic, não há qualquer diferença aparente entre chamar um método de extensão e os métodos que estão realmente definidos no tipo.

Os Extension Methods estão disponíveis no C# 3.0, a partir da versão 3.5 da Framework .NET e podem ser implementados em qualquer tipo, quer definido na framework quer definido pelo programador.

Uma das desvantagens consiste no facto de que, se criar um método de extensão com o mesmo nome de um método já existente no tipo, o compilador vai ligar a chamada ao método original e não à extensão. Os métodos de extensão só são chamados se não for encontrado nenhum método nativo com o mesmo nome.

Aviso

Se for declarado um método de extensão para o tipo Object, na realidade vai ser criado o método de extensão para todos os tipos da framework.

Como podemos criar Extension Methods

Vamos imaginar que pretendemos criar um método que retorna qualquer string, formatada como um nome pessoal, i.e., a primeira letra de cada palavra em maiúscula.

antónio josé silva -> António José Silva

A abordagem normal consiste em criar uma função e chamá-la sempre que se queira formatar uma string. Também é normal colocar essas funções numa classe utilitária:

public class MyUtilities
{
  public static string ToProperCase(string s)
  {
    if (s == null) 
      return null; 
    else
      return CultureInfo.CurrentUICulture.TextInfo.ToTitleCase (s); 
  }
}

Agora podemos converter uma string através duma chamada à função:

string test = "antónio josé silva";
Console.WriteLine(MyUtilities.ToProperCase(test));

No entanto, podemos estender a própria classe String, para suportar diretamente esta funcionalidade.


O procedimento básico para a criação de um método de extensão é o seguinte:




  1. Criar uma classe public static;


  2. Definir lá o método com as respectivas acções que se querem executar;


  3. Transformar esse método num Extension Method, com a utilização do modificador this.
public static class MyUtilities
{
  public static string ToProperCase(this string s)
  {
    if (s == null) 
      return null; 
    else
      return CultureInfo.CurrentUICulture.TextInfo.ToTitleCase (s); 
  }
}

A única coisa que o separa de qualquer outro método estático, é a palavras-chave this, nos parâmetros do método. Ela informa o compilador que este é um método de extensão para a classe string, e isso é realmente tudo que é necessário para criar um método de extensão.


Agora, podemos chamar o método ToProperCase() de forma directa:

string test = "antónio josé silva";
Console.WriteLine(test.ToProperCase());

Alguns exemplos de Extension Methods

Verifica se uma string é numérica:

public static bool IsNumeric(this string s)
{
  if (String.IsNullOrEmpty(s))
    return false;
  return Regex.IsMatch(s, "^[0-9]+$");
}
...
if (s.IsNumeric())
{
...

Verifica se uma string é representa um endereço de e-mail bem formatado:

public static bool IsValidEmail(this string s)
{
  if (String.IsNullOrEmpty(s))
    return false;
  
  s = s.Trim();
  var result = Regex.IsMatch(s, "^(?:[\\w\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\`\\{\\|\\}\\~]+\\.)*[\\w\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\`\\{\\|\\}\\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-](?!\\.)){0,61}[a-zA-Z0-9]?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\\[(?:(?:[01]?\\d{1,2}|2[0-4]\\d|25[0-5])\\.){3}(?:[01]?\\d{1,2}|2[0-4]\\d|25[0-5])\\]))$", RegexOptions.IgnoreCase);
  return result;
}
...
if (s.IsValidEmail())
{
...

Estes são apenas alguns exemplos de Extension Methods.


Poderão ver mais exemplos no seguinte endereço: extensionmethod.net

Sem comentários:

Enviar um comentário