viernes, 9 de agosto de 2013

Métodos de extensión en C#

Métodos de extensión en C#



Menú con rotación aleatoria
Los métodos de extensión son, básicamente, una forma de agregarle métodos a una clase sin necesidad de hacerlo en la original o en alguna instancia de la misma. Es un pequeño "truco" que permite darle más funcionalidad a una clase sin modificarla realmente.

Extendiendo una clase propia

Para lograr entender bien la idea detrás de los métodos de extensión, vamos a crear una clase propia llamada Persona que sólo tenga dos propiedades (nombre y apellido).
Para probar estos ejemplos vamos a utilizar un proyecto de consola.
Creamos un nuevo proyecto de consola; creamos una clase llamada Persona y le agregamos el siguiente código:
    public class Persona
{
    public Persona(string nombre, string apellido)
    {
        this.Nombre = nombre;
        this.Apellido = apellido;
    }


    public string Nombre { get; set; }
    public string Apellido { get; set; }
}
La clase sólo tiene las propiedades y un constructor. Si vamos al Main() de nuestro proyecto y creamos un objeto de la clase Persona, vamos a poder ver lo siguiente en el intellisense.
Métodos de extensión C#
Ahora creamos una nueva clase estática llamada Extensores y escribimos el siguiente código:
    public static class Extensores
{
    public static string ObtenerNombreCompleto(this Persona persona)
    {
        return persona.Nombre + " " + persona.Apellido;
    }
    }
Podemos notar las siguientes cosas sobre los métodos de extensión:
  • Deben estar contenidos en clases estáticas
  • Deben ser estáticos
  • Se debe indicar a qué clase se extiende mediante la palabra reservada this
Por lo tanto, si ahora nosotros compilamos el proyecto, los objetos de persona van a contar con este nuevo método (podemos ver este método cuenta con un ícono distinto que el resto).
Métodos de extensión C#

Extendiendo clases de terceros

Por lo visto hasta ahora, la lógica diría que si vamos a agregar un método nuevo a una clase, lo tendríamos que hacer dentro de la clase y no en otra a través de un método extensor. Y es verdad. Los métodos extensores son mucho más útiles para agregar en clases de terceros, de las cuales no contamos con el código fuente o por definición están selladas.
Para jugar un poco con esto, vamos a un caso específico. Vamos a crear un método para extender la clase Object y que nos indique si el objeto declarado es nulo.
    public static bool EsNulo(this Object obj)
{
    return obj == null;
}
Seguimos dentro de nuestra clase Extensores, esta vez extendemos la clase Object, y como en .NET todo deriva de esta clase, significa que todo objeto que creemos va a contar con este nuevo método.
Métodos de extensión C#

Extendiendo la clase String

Como último ejemplo, vamos a extender la clase String, la cual es sellada (lo que no nos permite crear una clase que derive de ella). Lo que vamos a hacer, es crear un método que nos devuelva la cantidad de palabras que contiene un texto.
Para lograrlo, dividimos la cadena en un arreglo de char (por los caracteres indicados) y contamos la cantidad de elementos que contiene el arreglo.
    public static int CantidadDePalabras(this string str)
    {
        return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
    }
Gracias a eso, podemos hacer algo como lo siguiente.
    //texto aleatorio
    string loremIpsum = @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
                        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
                        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
                        consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
                        cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
                        proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";


Console.WriteLine("Cantidad de palabras: " + loremIpsum.CantidadDePalabras());

Resumen

Gracias a los métodos de extensión se puede obtener un código más legible y mantenible, pero tiene sus inconvenientes:
  • El ciclo de vida de la clase y de los métodos que la extienden pueden ser diferentes
  • Sin el Intellisense es muy difícil saber si un método pertenece a una clase o la extiende
  • Si se agrega en la clase extendida un método con el mismo nombre que el extendido, el extensor dejará de funcionar.
A pesar de estas contras, esta funcionalidad es tan potente, que herramientas como Linq están construidas con esta técnica de desarrollo.
¿Usás métodos de extensión en tus proyectos?