C# 3.0 – Extension Methods

Suponha que, num método C#, tenhamos uma variável do tipo string chamada  “data”.
O que faz o trecho de código abaixo?

data.Substring(0, 2);

E o este aqui?

data.Substring(data.Length – 2);

O primeiro trecho de código retorna os 2 primeiros caracteres da string existente
na variável “data”. Já o segundo trecho de código retorna os últimos 2 caracteres
da mesma string.

A semântica imposta pelo código acima não denuncia a sua real intenção num primeiro
momento, correto? Seria, por acaso, mais fácil se tivéssemos o seguinte?

data.Left(2);

e

data.Right(2);

Na minha opinião, sim! E, na verdade, sempre senti falta desses métodos na BCL do
.NET. Uma alternativa seria criarmos uma nova classe derivada de System.String
e acrescentarmos esses métodos a essa classe. Pena que isso não é possível. A
classe string no .NET é selada (sealed) e, portanto, não pode ser estendida.

Felizmente, o C# 3.0 trará um recurso muito interessante chamado “Extension Methods”.
Esta funcionalidade da linguagem é altamente explorada pelo LINQ (Language Integrated
Query), mas vamos nos deter aqui ao funcionamento desse recurso na linguagem. É possível
usarmos exatamente o código apresentado acima lançando mão de Extension Methods. A
primeira coisa que temos que fazer é criar uma classe estática com os métodos Left
e Right (classes estáticas também são novas no C# 3.0 e são classes compostas somente
de métodos estáticos). O código abaixo mostra a definição dessa classe:

namespace MyExtensions
{
    public
static class
StringExtensions
    {
        public
static string
Left(this string text, int
numberOfCharacters)
       
{
            return text.Substring(0,
numberOfCharacters);
       
}
>



        public
static string
Right(this string text, int
numberOfCharacters)
       
{
            return text.Substring(text.Length
– numberOfCharacters);
       
}
    }
}

Note que os métodos são definidos com dois parâmetros, mas somente
um deles é efetivamente passado na chamada do método. O primeiro parâmetro de um Extension
Method, na realidade, define o tipo ao qual o método se aplica (no caso o tipo string).
Para que este método possa ser caracterizado pelo compilador como um Extension Method,
e não como um mero método com 2 parâmetros, a palavra reservada “this” é colocada
à frente do nome do tipo na declaração do método. Isso denota, assim, que os métodos
Left e Right são Extension Methods para o tipo string.

Como o nome já diz, Extension métodos estentem o comportamente
de um tipo. No caso, estamos estendendo o comportamento do tipo string. Mas não estamos
fazendo isso com todas as strings existentes em todos os nosso programas. Extension
Methods só são usados pelas classes que importam o namespace que contém os Extension
Methods. No nosso exemplo, os nossos Extension Methods estão definidos na classe “StringExtensions” do
namespace “MyExtensions“. Para que possamos usar esses
métodos em uma outra classe qualquer no nossso programa, temos que importar a namespace
“MyExtensions” e compilador se encarregará de descobrir quais são os Extension Methods
declarados nas classes deste namespaces, resolvendo-os em tempo de compilação.

O exemplo abaixo usa um método de teste para ilustrar a utilização dos nossos Extension
Methods:

using
System;
using
Microsoft.VisualStudio.TestTools.UnitTesting;
using MyExtensions;>

namespace
ExtensionMethodsTests
{
    [
TestClass
]
    public class
ExtensionMethodsTest
    {
        [
TestMethod
]
        public void
TestExtensionMethodsLeftAndRight()
        {
           
string
date = “2006-07-03″
;
           
string
year = date.Left(4);
           
string
day = date.Right(2);>

           
Assert
.AreEqual(“2006”
,
year);
           
Assert
.AreEqual(“03”,
day);
       
}
    }
}

>

Note que, para que as chamadas aos Extension Methods funcionem, precisamos importar
o namespace “MyExtensions”. Mas isso é tudo o que precisamos fazer.

Cool, huh?

 

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>