2008-12-31 25 views
38

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



EDIT: He publicado una pregunta de seguimiento en Usage of Extension Methods

+1

Para su seguimiento, vea mi respuesta a continuación. Básicamente crearía extensiones en lugar de usar herencia. –

+0

@Tom Anderson - ¿Entonces la decisión de crear métodos de extensión se basa principalmente en el acceso a la fuente? – Developer

+1

en mi caso, sí. Otra instancia es la facilidad, en lugar de heredar de System.Windows.Forms.Form y agregar el método y luego modificar toda mi fuente para usar esa clase base, simplemente escribo la extensión y todas las formas la tienen ahora. –

Respuesta

50

Los métodos de extensión permiten a los desarrolladores añadir nuevos métodos a la contrato público de un tipo CLR existente, sin tener que subclase o recompilar el tipo original.

métodos de extensión ayudar a mezclar el flexibilidad de apoyo "duck typing" popular dentro de los lenguajes dinámicos hoy con el rendimiento y tiempo de compilación validación de tipo fuerte idiomas.

Referencia: http://weblogs.asp.net/scottgu/archive/2007/03/13/new-orcas-language-feature-extension-methods.aspx

Este es un ejemplo de un método de extensión (nótese la this palabra clave enfrente del primer parámetro):

public static bool IsValidEmailAddress(this string s) 
{ 
    Regex regex = new Regex(@"^[\w-\.][email protected]([\w-]+\.)+[\w-]{2,4}$"); 
    return regex.IsMatch(s); 
} 

Ahora, el método anterior puede ser llamado directamente desde cualquier cadena, como tal:

bool isValid = "[email protected]".IsValidEmailAddress(); 

Los métodos añadidos entonces también aparecen en IntelliSense:

alt text http://www.scottgu.com/blogposts/extensionmethods/step1.jpg

En cuanto a un uso práctico para métodos de extensión, se podría añadir nuevos métodos a una clase sin derivar una nueva clase.

Tome un vistazo al siguiente ejemplo:

public class Extended { 
    public int Sum() { 
     return 7+3+2; 
    } 
} 

public static class Extending { 
    public static float Average(this Extended extnd) { 
     return extnd.Sum()/3; 
    } 
} 

Como se ve, la clase Extending es la adición de un llamado a la clase media método Extended.Para obtener el promedio, se llama a average método, ya que pertenece a extended clase:

Extended ex = new Extended(); 

Console.WriteLine(ex.average()); 

Referencia: http://aspguy.wordpress.com/2008/07/03/a-practical-use-of-serialization-and-extension-methods-in-c-30/

+5

100% correcto, aunque no puedo evitar agregar métodos de extensión a tipos primitivos como cadenas que no son fundamentales para el tipo. Por lo tanto, no agregaría 'IsValidEmailAddress' a la cadena, pero he agregado Left (int) y Right (int). –

5

métodos de extensión son maneras para que los desarrolladores "añadido" a los métodos de objetos que no pueden controlar.

Por ejemplo, si desea agregar un método "DoSomething()" al objeto System.Windows.Forms, ya que no tiene acceso a ese código, simplemente debe crear un método de extensión para el formulario con la siguiente sintaxis

Public Module MyExtensions 

    <System.Runtime.CompilerServices.Extension()> _ 
    Public Sub DoSomething(ByVal source As System.Windows.Forms.Form) 
     'Do Something 
    End Sub 

End Module 

Ahora dentro de un formulario puede llamar a "Me.DoSomething()".

En resumen, es una forma de agregar funcionalidad a objetos existentes sin herencia.

3

un método de extensión es un "truco compilador" que le permite simular la adición de métodos a otra clase, incluso si no tiene el código fuente para ello.

Por ejemplo:

using System.Collections; 
public static class TypeExtensions 
{ 
    /// <summary> 
    /// Gets a value that indicates whether or not the collection is empty. 
    /// </summary> 
    public static bool IsEmpty(this CollectionBase item) 
    { 
     return item.Count == 0; 
    } 
} 

En teoría, todas las clases de colección incluyen ahora un método IsEmpty que devuelve verdadero si el método no tiene elementos (siempre y cuando se haya incluido el espacio de nombres que define la clase anterior).

Si me he perdido algo importante, estoy seguro de que alguien lo señalará. (Por favor!)

Naturalmente, existen reglas sobre la declaración de los métodos de extensión (deben ser estáticos, el primer parámetro debe ir precedido de la palabra clave this, y así sucesivamente).

Los métodos de extensión en realidad no modifican las clases que parecen extenderse; en cambio, el compilador manipula la llamada a la función para invocar el método de manera adecuada en tiempo de ejecución. Sin embargo, los métodos de extensión aparecen correctamente en listas desplegables intellisense con un ícono distintivo, y puede documentarlos como lo haría con un método normal (como se muestra arriba).

Nota: un método de extensión no sustituye a un método si un método ya existe con la misma firma.

+0

Buena captura. Solucionado el código. –

1

Aquí está el ejemplo en VB.Net; observe el atributo Extensión(). Coloque esto en un Módulo en su proyecto.

Imports System.Runtime.CompilerServices 
<Extension()> _ 
Public Function IsValidEmailAddress(ByVal s As String) As Boolean 
    If String.IsNullOrEmpty(s) Then Return False 

    Return Regex.IsMatch(email, _ 
     "^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$") 
End Function 
0

Esta pregunta ya ha sido contestada, pero me gustaría añadir que es muy útil si usted tiene tipos que están dentro de otro proyecto y no quiere volver a ese proyecto en Para agregar alguna funcionalidad. Estamos usando NHibernate y tenemos un proyecto para nuestra capa de persistencia de datos que los chicos quieren mantener limpio. Con el fin de obtener métodos adicionales agradables y reconocibles en esos objetos, pude usar métodos de extensión y realmente me alegraron el día.

También, ya que nadie más ha publicado, aquí está un buen artículo sobre el tema en MSDN - http://msdn.microsoft.com/en-us/library/bb383977.aspx

7

Por qué estoy escribiendo otra respuesta?

Las respuestas anteriores son demasiado complejas. Supongo que si necesita preguntar qué es un método de extensión, realmente no sabrá lo que significa: (i) contratos públicos, (ii) CLR, (iii) tipos, (iv) subclase, (v) de pato a escribir, etc.

Vamos a mantenerlo simple - Métodos de extensión Explicado

Supongamos que tengo un perro. Un perro es un "tipo" de animal.Todos los perros - todos los animales de tipo perro - hacer ciertas cosas:

  1. Coma
  2. WagsTail
  3. gritos
  4. Shakes la pata etc

Las cosas que un perro puede “Woof!” todos se llaman "métodos".

Supongamos ahora que el Gran Programador en OO Heaven olvidó agregar un método a la clase de perro. Supongamos que desea que todos los perros de su hogar hagan algo adicional: FetchNewspaper.

usted quiere ser capaz de decir:

rex.FetchNewspaper(); // or 
wolfie.FetchNewspaper(); // or 
beethoven.FetchNewspaper(); 

...... a pesar de que no tiene acceso al código fuente. Wolfie, Rex y Beethoven son perros en tu hogar de mascotas por cierto.

¿Cómo te va para que tu perro haga eso?

Debería volver a compilar. ¡Pero no tienes el código fuente! Si no tiene el código fuente, entonces no puede agregar el método al lugar relevante en el código.

Su única solución es crear un "método de extensión".

Creación de un método de extensión

(Nótese la palabra “this” delante del primer parámetro a continuación):

public static void FetchNewsPaper(this Dog familyDog) 
{ 
    ConsoleWriteline(“Goes to get newspaper!”) 
} 

Y si desea que su perro para conseguir el periódico simplemente hacer esto :

Dog freddie_the_family_dog = new Dog(); 

freddie_the_family_dog.FetchNewspaper(); 

Si no tiene los métodos de extensión, entonces no sería capaz de pedir a Freddie_the_family_dog FETC h periódicos.

¿Qué acabamos de hacer?

Añadimos un método adicional para que todos los perros tengan la capacidad de buscar periódicos.

¿Cómo funciona?

Simplemente: (i) llame a su perro, y (ii) dígale que busque el papel. Lo que no puede hacer es decir "Buscar un periódico" sin especificar qué perro, en su familia, debe hacer la recolección.

Espero que eso te ayude. Si todavía tiene preguntas, publique un comentario y haré todo lo posible para explicarlo.

0

Pensé que agregaría una explicación que es más conceptual y menos dependiente del código.

Imagine un Ford saliendo de la línea de construcción. No tiene acceso a la línea de construcción, pero desea que todos los autos de Ford puedan tener un alerón adicional agregado a la parte trasera del automóvil (se ve más frío cuando se exhibe). ¿Cómo vas a hacer eso?En el mundo de la informática, a menos que tenga acceso a la línea de construcción original dentro de una fábrica de Ford, no puede simplemente atornillar cosas al Ford. Bien, ahora puedes: INTRODUZCA métodos de extensión.

Ahora usted puede hacer cosas como esta:

Ford hilux = new Ford(); 

hilux.DisplayRearFoiler(); // you can now do this even though you don't have access to the Ford source code. 

Vas a tener que crear el método de extensión. Consulte las respuestas anteriores.

0

Quiero responder a los métodos de extensión en términos de Clase sellada.

Supongamos que tiene una clase sellada que contiene métodos vitales. Ahora quiere agregarle un nuevo método. Supongamos que esta clase viene en una DLL externa por lo que no puede agregarle un nuevo método. Qué harás ?

Tome otro ejemplo. Supongamos que la clase está integrada en su aplicación por su Project Manager o Security Guru. Puede editar esa clase solo tomando el permiso de su Project Manager o Security Guru.

Su solución puede ser eliminar la palabra clave sellada de esta clase y heredarla en otra clase. Luego, dentro de la subclase (que hereda esta clase) puede agregar su nuevo método.

Pero espere -> No puede simplemente eliminar la palabra clave sellada ya que esto puede comprometer la seguridad de toda la aplicación. Puedo apostarle que su PM o Security Guru nunca le dará ese permiso citando problemas de seguridad.

¿Qué se puede hacer aquí?

La respuesta es Métodos de extensión que se pueden agregar en una clase estática y ya no necesita tocar la clase sellada.

Ejemplo: -

sealed class MyData 
{ 
    private double D1, D2, D3; 
    public MyData(double d1, double d2, double d3) 
    { D1 = d1; D2 = d2; D3 = d3; } 
    public double Sum() { return D1 + D2 + D3; } 
} 

static class ExtendMyData 
{ 
    public static double Average(this MyData md) 
    { 
     return md.Sum()/3; 
    } 
} 

he añadido un método estático público denominado media a una nueva clase estática. Este método tiene el parámetro de la clase principal con la palabra clave 'this' al frente.

Ahora, para llamar al método Average, utilizo el objeto de la clase primaria sellada y no la subclase.

MyData md = new MyData(3, 4, 5); 
double exAverage = md.Average(); 

Espero que encuentres métodos de extensión útiles.

Cuestiones relacionadas