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:
System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MyExtensions; ExtensionMethodsTests
{
[TestClass]
public class ExtensionMethodsTest
{
[TestMethod]
public void TestExtensionMethodsLeftAndRight()
{
string date = "2006-07-03";
string year = date.Left(4);
string day = date.Right(2);
namespace
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?
using
