Los métodos de extensión permiten "agregar" métodos 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 métodos de extensión constituyen un tipo especial de método estático, pero se les llama como si se tratasen de métodos de instancia en el tipo extendido. En el caso del código de cliente escrito en C# y Visual Basic, no existe ninguna diferencia aparente entre llamar a un método de extensión y llamar a los métodos realmente definidos en un tipo.
Los métodos de extensión más comunes son los operadores de consulta estándar de LINQ que agregan funcionalidad de consulta a los tipos System.Collections..::.IEnumerable y System.Collections.Generic..::.IEnumerable<(Of <(T>)>) existentes. Para utilizar los operadores de consulta estándar, primero inclúyalos en el ámbito con una directiva using System.Linq. Después, cualquier tipo que implemente IEnumerable<(Of <(T>)>) parecerá tener métodos de instancia como GroupBy, OrderBy, Average, etc. Puede ver estos métodos adicionales con la característica de finalización de instrucciones IntelliSense al escribir un "punto" después de una instancia de un tipo IEnumerable<(Of <(T>)>) como List<(Of <(T>)>) o Array.
En el ejemplo siguiente se muestra cómo llamar al método de operador de consulta estándar OrderBy en una matriz de enteros. La expresión entre paréntesis es una expresión lambda. Muchos operadores de consulta estándar usan expresiones lambda como parámetros, pero no es obligatorio para los métodos de extensión. Para obtener más información, consulte Expresiones lambda (Guía de programación de C#).
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 métodos de extensión se definen como métodos estáticos pero se llaman utilizando la sintaxis de los métodos de instancia. El primer parámetro especifica en qué tipo actúa el método y va precedido del modificador this. Los métodos de extensión sólo se incluyen en el ámbito cuando el espacio de nombres se importa explícitamente al código fuente con una directiva using.
En el ejemplo siguiente se muestra un método de extensión definido para la clase System..::.String. Observe que se define dentro de una clase estática no anidada y no genérica:
namespace ExtensionMethods
{
public static class MyExtensions
{
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
}
}
El método de extensión WordCount se puede incluir en el ámbito con esta directiva using:
También se puede llamar desde una aplicación con esta sintaxis:
string s = "Hello Extension Methods";
int i = s.WordCount();
En el código, el método de extensión se invoca con sintaxis de método de instancia. Sin embargo, el lenguaje intermedio (IL) generado por el compilador convierte el código en una llamada en el método estático. Por lo tanto, no se infringe realmente el principio de encapsulación. De hecho, los métodos de extensión no pueden tener acceso a las variables privadas del tipo que extienden.
Para obtener más información, consulte Cómo: Implementar e invocar un método de extensión personalizado (Guía de programación de C#).
En general, probablemente llamará a métodos de extensión con mayor frecuencia de lo que implementará los suyos propios. Dado que se llama a los métodos de extensión con sintaxis de método de instancia, no se requieren conocimientos especiales para usarlos desde el código de cliente. Para habilitar los métodos de extensión para un tipo determinado, simplemente agregue una directiva using para el espacio de nombres en el que se definen los métodos. Por ejemplo, para utilizar los operadores de consulta estándar, agregue esta directiva using a su código:
(Puede que tenga que agregar también una referencia a System.Core.dll.) Observará que los operadores de consulta estándar ahora aparecen en IntelliSense como métodos adicionales disponibles para la mayoría de los tipos IEnumerable<(Of <(T>)>).
Nota: |
|---|
Aunque no aparezcan operadores de consulta estándar en IntelliSense para String, siguen estando disponibles. |