Métodos de extensión

En este post vamos a ver qué son los métodos de extensión y cómo se implementan. Además veremos algún ejemplo donde se usa.

¿Qué son los métodos de extensión?

Los métodos de extensión nos permiten agregar métodos a clases existentes sin necesidad de tener que heredar de ellas. Esto es así porque algunas clases son selladas, es decir, que nadie puede heredar de ellas, como por ejemplo la clase System.String. Los método de extensión constituyen un tipo especial de métodos estáticos pero se llama como si se tratasen de métodos de instancia.

¿Cómo se implementan?

Vamos a ver como se implementa a través de un ejemplo. Vamos a hacer dos métodos de extensión para la clase string. El primero va a ser un método que nos indicará si toda la cadena está en mayúsculas y otro que cuenta las apariciones de un carácter en la cadena. Éste último método recibe como parámetro un carácter.

Para implementar los métodos de extensión lo que debemos hacer es crear una clase estática. El nombre no importa, lo importante es la firma de los métodos.

Dentro de la clase estática que hemos creado añadimos un método estático cuyo primer parámetro será del tipo que queremos extender y llevará la palabra reservada this delante.

 public static bool IsUpperText(this string value)

Siguiendo esta nomenclatura ya hemos extendido la clase string con nuestro método IsUpperText. Como podemos ver en la imagen, nuestro método aparece como extensión de la clase string y lo llamamos como un método de instancia pese a que hemos declarado el método estático.

extension

Es importante mencionar que debemos incluir el namespacedonde se encuentra el método extendido para que podamos utilizarlo. De esta forma en otro fichero donde no esté incluido el namespace la clase string no tendrá el método IsUpperText.

Vamos a ver el cuerpo del método.

 public static bool IsUpperText(this string value)
{
    bool isUpper = true;
    foreach (var item in value)
    {
        if(char.IsLetter(item) && !char.IsUpper(item))
        {
            isUpper = false;
            break;
        }
    }
    return isUpper;
}

Ahora vamos a ver otro ejemplo en el que extendemos la clase string con un método que recibe un parámetro. Funciona exactamente igual que el anterior, el primer parámetro debe ser del tipo que queremos extender y precedido de la palabra this. A continuación podemos indicarle otros parámetros, en nuestro caso uno de tipo char.

 public static int CountChars(this string value, char c)

Aquí podemos ver el cuerpo del método, que cuenta el número de apariciones del carácter que se le pasa por parámetro.

 public static int CountChars(this string value, char c)
{
    int count = 0;
    foreach (var item in value)
    {
        if(item == c)
        {
            count++;
        }
    }
    return count;
}

Vamos a ver un ejemplo de ejecución de nuestro código.

 string str = "Metodos de extension";
string upperText = "HOLA MUNDO";
string noUpperText = "HoLA MUNDO";

Console.WriteLine("IsUpperText('" + upperText + "'): " + upperText.IsUpperText());

Console.WriteLine("IsUpperText('" + noUpperText + "'): " + noUpperText.IsUpperText());

Console.WriteLine("Count de 'e' en '" + str + "': " + str.CountChars('e'));
example

Interfaces

Como hemos visto anteriormente podemos extender una clase. Ahora bien, no podemos invalidar el método de una clase, es decir, si extendemos una clase con el mismo nombre y mismos parámetros de un método que ya tienen la clase o interfaz se llamará siempre al método propio de la clase.

Cuando el compilador encuentra una referencia a un método buscará siempre primero entre los métodos de instancia del tipo y si no lo encuentra buscará entre los métodos de extensión.

Por ejemplo si extendemos el método ToString de la siguiente forma:

 public static string ToString(this string str)
{
    return "Esta frase no debería salir";
}

Al ejecutar nuestro código obtendremos lo siguiente.

 Console.WriteLine("ToString de '" + str + "': " + str.ToString());

tostring

 

Como vemos no ha ejecutado el método de extensión sino el propio método de la clase string.

Ejemplo de uso de los métodos de extensión

Uno de los ejemplos más claros de esto son los métodos que añade LINQ para trabajar con enumeraciones. Como podemos ver al agregar el namespace de LINQ nos aparecen métodos de extensión que enriquecen mucho los INumerables.

 using System.Linq;

 linq

Un saludo,

Sergio Gallardo Sales (@maktub82)

 

PD: Mantente informado de todas las novedades de Microsoft para los desarrolladores españoles a través del Twitter de MSDN, el Facebook de MSDN, el Blog de MSDN y la Newsletter MSDN Flash.