You are on page 1of 8

Mtodos de extensin (Gua de programacin de C#)

Visual Studio 2010 Otras versiones

Visual Studio 2008

Los mtodos de extensin permiten "agregar" mtodos a los tipos existentes sin necesidad de crear un nuevo tipo derivado y volver a compilar o sin necesidad de modificar el tipo original. Los mtodos de extensin constituyen un tipo especial de mtodo esttico, pero se les llama como si se tratasen de mtodos de instancia en el tipo extendido. En el caso del cdigo de cliente escrito en C# y Visual Basic, no existe ninguna diferencia aparente entre llamar a un mtodo de extensin y llamar a los mtodos realmente definidos en un tipo. Los mtodos de extensin ms comunes son los operadores de consulta estndares LINQque agregan la funcionalidad de la consulta a los tipos System.Collections.Generic.IEnumerable<T> y los System.Collections.IEnumerable existentes. utilizar los operadores de consulta estndares, primero introdzcalos en el mbito con una directiva using System.Linq. Despus, cualquier tipo que implemente IEnumerable<T> parecer tener mtodos de instancia como GroupBy, OrderBy, Average, etc. Puede ver estos mtodos adicionales con la caracterstica de finalizacin de instrucciones IntelliSense al escribir un "punto" despus de una instancia de un tipo IEnumerable<T> como List<T> o Array. En el ejemplo siguiente se muestra cmo llamar al mtodo de operador de consulta estndar OrderBy en una matriz de enteros. La expresin entre parntesis es una expresin lambda. Muchos operadores de consulta estndar usan expresiones lambda como parmetros, pero no es obligatorio para los mtodos de extensin. Para obtener ms informacin, vea Expresiones lambda (Gua de programacin de C#).

VB C# C++

F# JScript

class ExtensionMethods2 { static void Main() { int[] ints = { 10, 45, 15, 39, 21, 26 }; var result = ints.OrderBy(g => g); foreach (var i in result) { System.Console.Write(i + " "); } } } //Output: 10 15 21 26 39 45

Los mtodos de extensin se definen como mtodos estticos pero se llaman utilizando la sintaxis de los mtodos de instancia. El primer parmetro especifica en qu tipo acta el mtodo y va precedido del modificador this. Los mtodos de extensin slo se incluyen en el mbito cuando el espacio de nombres se importa explcitamente al cdigo fuente con una directiva using. En el ejemplo siguiente se muestra un mtodo de extensin definido para la clase System.String. Observe que se define dentro de una clase esttica no anidada y no genrica:

VB C# C++ F# JScript

namespace ExtensionMethods { public static class MyExtensions { public static int WordCount(this String str) { return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length; } } }

El mtodo de extensin WordCount se puede incluir en el mbito con esta directiva using:
using ExtensionMethods;

Tambin se puede llamar desde una aplicacin con esta sintaxis:


string s = "Hello Extension Methods"; int i = s.WordCount();

En el cdigo, el mtodo de extensin se invoca con sintaxis de mtodo de instancia. Sin embargo, el lenguaje intermedio (IL) generado por el compilador convierte el cdigo en una llamada en el mtodo esttico. Por lo tanto, no se infringe realmente el principio de encapsulacin. De hecho, los mtodos de extensin no pueden tener acceso a las variables privadas del tipo que extienden. Para obtener ms informacin, vea Cmo: Implementar e invocar un mtodo de extensin personalizado (Gua de programacin de C#). En general, probablemente llamar a mtodos de extensin con mayor frecuencia de lo que implementar los suyos propios. Dado que se llama a los mtodos de extensin con sintaxis de mtodo de instancia, no se requieren conocimientos especiales para usarlos desde el cdigo de cliente. Para habilitar los mtodos de extensin para un tipo determinado, simplemente agregue una directiva using para el espacio de nombres en el que se definen los mtodos. Por ejemplo, para utilizar los operadores de consulta estndar, agregue esta directiva using a su cdigo:

using System.Linq;

(Puede que tenga que agregar tambin una referencia a System.Core.dll.) Observar que los operadores de consulta estndar ahora aparecen en IntelliSense como mtodos adicionales disponibles para la mayora de los tipos IEnumerable<T>. Nota Aunque no aparezcan operadores de consulta estndar en IntelliSense para String, siguen estando disponibles. Enlazar mtodos de extensin en tiempo de compilacin

Puede utilizar mtodos de extensin para extender una clase o una interfaz, pero no para invalidarlas. Nunca se llamar a un mtodo de extensin que tenga el mismo nombre y firma que un mtodo de interfaz o clase. En tiempo de compilacin, los mtodos de extensin siempre tienen menos prioridad que los mtodos de instancia definidos en el propio tipo. En otras palabras, si un tipo tiene un mtodo denominado Process(int i) y hay un mtodo de extensin con la misma firma, el compilador siempre establecer el enlace con el mtodo de instancia. Cuando el compilador encuentra una invocacin de mtodo, busca primero una coincidencia entre los mtodos de instancia del tipo. Si no la encuentra, buscar cualquier mtodo de extensin definido para el tipo y establecer el enlace con el primer mtodo de extensin que encuentre. En el ejemplo siguiente se muestra cmo el compilador determina con qu mtodo de extensin o mtodo de instancia establecer el enlace. Ejemplo

En el ejemplo siguiente se muestran las reglas que sigue el compilador de C# para determinar si debe establecer un enlace entre una llamada a mtodo y un mtodo de instancia del tipo o un mtodo de extensin. La clase esttica Extensions contiene mtodos de extensin definidos para cualquier tipo que implementa IMyInterface. Las clases A, B y C implementan la interfaz. Nunca se llama al mtodo de extensin MethodB porque su nombre y firma coinciden exactamente con mtodos ya implementados por las clases. Si el compilador no encuentra un mtodo de instancia con una firma coincidente, establecer el enlace con un mtodo de extensin coincidente, en caso de que exista.

VB C# C++ F# JScript

// Define an interface named IMyInterface. namespace DefineIMyInterface { using System; public interface IMyInterface { // Any class that implements IMyInterface must define a method // that matches the following signature. void MethodB(); } } // Define namespace { using using extension methods for IMyInterface. Extensions System; DefineIMyInterface;

// The following extension methods can be accessed by instances of any // class that implements IMyInterface. public static class Extension { public static void MethodA(this IMyInterface myInterface, int i) { Console.WriteLine ("Extension.MethodA(this IMyInterface myInterface, int i)"); } public static void MethodA(this IMyInterface myInterface, string s) { Console.WriteLine ("Extension.MethodA(this IMyInterface myInterface, string s)"); } // This method is never called in ExtensionMethodsDemo1, because each

// of the three classes A, B, and C implements a method named MethodB // that has a matching signature. public static void MethodB(this IMyInterface myInterface) { Console.WriteLine ("Extension.MethodB(this IMyInterface myInterface)"); } } }

// Define three classes that implement IMyInterface, and then use them to test // the extension methods. namespace ExtensionMethodsDemo1 { using System; using Extensions; using DefineIMyInterface; class A : IMyInterface { public void MethodB() { Console.WriteLine("A.MethodB()"); } } class B : IMyInterface { public void MethodB() { Console.WriteLine("B.MethodB()"); } public void MethodA(int i) { Console.WriteLine("B.MethodA(int i)"); } } class C : IMyInterface { public void MethodB() { Console.WriteLine("C.MethodB()"); } public void MethodA(object obj) { Console.WriteLine("C.MethodA(object obj)"); } } class ExtMethodDemo { static void Main(string[] args) { // Declare an instance of class A, class B, and class C. A a = new A(); B b = new B(); C c = new C(); // For a, b, and c, call the following methods: // -- MethodA with an int argument // -- MethodA with a string argument // -- MethodB with no argument. // A contains no MethodA, so each call to MethodA resolves to

// the extension method that has a matching signature. // Extension.MethodA(object, int) a.MethodA(1); a.MethodA("hello"); // Extension.MethodA(object, string) // A has a method that matches the signature of the following call // to MethodB. a.MethodB(); // A.MethodB()

// B has methods that match the signatures of the following // nethod calls. // B.MethodA(int) b.MethodA(1); b.MethodB(); // B.MethodB() // B has no matching method for the following call, but // class Extension does. // Extension.MethodA(object, string) b.MethodA("hello"); // C contains an instance method that matches each of the following // method calls. c.MethodA(1); c.MethodA("hello"); c.MethodB(); } } } /* Output: Extension.MethodA(this IMyInterface myInterface, int i) Extension.MethodA(this IMyInterface myInterface, string s) A.MethodB() B.MethodA(int i) B.MethodB() Extension.MethodA(this IMyInterface myInterface, string s) C.MethodA(object obj) C.MethodA(object obj) C.MethodB() */ // C.MethodA(object) // C.MethodA(object) // C.MethodB()

Instrucciones generales

En general, recomendamos que implemente mtodos de extensin en contadas ocasiones, slo cuando sea necesario. Siempre que sea posible, cuando el cdigo de cliente debe extender un tipo existente, debe hacerlo creando un nuevo tipo derivado del existente. Para obtener ms informacin, vea Herencia (Gua de programacin de C#). Al utilizar un mtodo de extensin para extender un tipo cuyo cdigo fuente no se puede cambiar, corre el riesgo de que un cambio en la implementacin del tipo interrumpa su mtodo de extensin. Si implementa mtodos de extensin para un tipo determinado, recuerde los dos puntos siguientes:

y y

Nunca se llamar a un mtodo de extensin si tiene la misma firma que un mtodo definido en el tipo. Los mtodos de extensin se incluyen en el mbito en el nivel de espacio de nombres. Por ejemplo, si tiene varias clases estticas que contienen mtodos de extensin en un espacio de nombres nico denominado Extensions, la directiva using Extensions; los incluir a todos en el mbito.

Vea tambin

Referencia Expresiones lambda (Gua de programacin de C#) Conceptos Gua de programacin de C# Informacin general sobre operadores de consulta estndar Otros recursos Conversion rules for Instance parameters and their impact Extension methods Interoperability between languages Extension methods and Curried Delegates Extension method Binding and Error reporting Historial de cambios

You might also like