¿Que son los métodos de extensión?
Los métodos de extensión permiten “agregar” métodos a los tipos existentes sin crear un nuevo tipo derivado, recompilar o modificar de otra manera el tipo original. Son una clase especial de método estático, pero se les llama como si fueran métodos de instancia en el tipo extendido.
¿Para qué sirven?
Nos permiten agregar funcionalidad a un tipo existente sin tener que modificarlo. Esto nos ayudará a crear código limpio (sencillo, fácil de entender y fácil de mantener).
Estos tipos pueden haber sido creados por nosotros o tipos cuyo código fuente no podamos cambiar. El ejemplo más habitual es LINQ, la librería System.Linq agrega funcionalidades de consulta a los tipos System.Collection.IEnumerable y System.Collections.Generic.IEnumerable<T> existentes.
Vamos a ver un caso práctico. Imaginemos que tenemos una lista de usuarios y queremos extraer de esta lista todos los que estén activos (a través de un campo booleano IsActive).
Si utilizamos Linq con un simple Where (que es un método de extensión) obtenemos la lista que queremos, en cambio si no utilizamos Linq, nos queda un código más difícil de leer.
No quiero pasar por alto el comentar que a nivel de performance un bucle for sencillo siempre va a ser más rápido que cualquier combinación con Linq que hagamos. Se puede comprobar ejecutando el código anterior y mirando los tiempos. Para ello, tened en cuenta que Linq con su método where utiliza “ejecución aplazada” o “deferred execution”, por lo que si no se fuerza a obtener los resultados, con el metodo ToList() por ejemplo, realmente no estará haciendo la consulta.
¿Cómo hago extensiones?
Ahora que ya sabemos que son los métodos de extensión vamos a ver cómo crearlos.
Sintaxis
Los métodos de extensión deben definirse en una clase estática no genérica y estos métodos deben de ser estáticos. El primer parámetro especifica en que tipo funciona el método, y el parámetro debe estar precedido del modificador this. Nuestro método de extensión no debe coincidir en nombre ni en firma con los métodos de la propia clase que estamos extendiendo.
Ejemplo
Supongamos que en nuestra aplicación no realizamos borrados físicos, sino que los borrados son lógicos notificando un campo DropDate. Pues bien, vamos a crear una extensión para obtener a partir de un IEnumerable<T> comprobar si tiene una propiedad DropDate igual a null, lo que implicaría que el objeto no ha sido borrado. Y ya que estamos, el nombre de la propiedad vendrá por parámetro para hacerlo más reutilizable.
Creación de la extensión
Para este ejemplo, lanzamos una excepción si el elemento T no contiene la property con el nombre indicado y devolvemos los resultados utilizando “ejecución aplazada” o “deferred execution” con la instrucción yield return, siguiendo el estilo de Linq.
Nota: Sería altamente recomendable incluir un summary con una breve explicación del método.
Utilización de la extensión
Gracias a la extensión, podemos obtener todos los usuarios que tienen la property DropDate igual a null con una simple línea. Además, nos serviría para cualquier property de cualquier clase.
Utilizando varios métodos de extensión y con fluent interface, podemos crear código limpio al estilo Linq. En este caso particular podríamos combinar este método de extensión junto a los de Linq debido a que trabajamos con IEnumerable<T>.
Conclusiones
Es recomendable utilizar los métodos de extensión con moderación y solo cuando sea necesario. Habitualmente se recomienda utilizar métodos de instancia o recurrir a herencia en vez de utilizar métodos de extensión. Y nos encontraremos con casos en los que la mejor opción será utilizar métodos de instancia o herencia.
Hay que tener en cuenta que si realizamos extensiones de tipos que vienen de librerías externas, si estas cambian podrían hacer que nuestra extensión dejase de funcionar. Por ejemplo, si al tipo se le añadiese un método el mismo nombre y misma firma nuestra extensión dejaría de funcionar ya que prevalecería el método del tipo.
Antonio Cárdenas
Sofware Engineer I Soluciones Microsoft I SOGETI
0 comments on “Métodos de extensión para C#”