2009-07-27 28 views
80

¿Se pueden aplicar métodos de extensión a la clase?¿Cómo extiendo una clase con los métodos de extensión C#?

Por ejemplo, se extienden DateTime para incluir un método Mañana() que pueda ser invocada como:

DateTime.Tomorrow(); 

Sé que puedo utilizar

static DateTime Tomorrow(this Datetime value) { //... } 

O

public static MyClass { 
    public static Tomorrow() { //... } 
} 

de un resultado similar, pero ¿cómo puedo extender DateTime para poder invocar DateTime.Tomorrow?

Respuesta

63

No puede agregar métodos a un tipo existente a menos que el tipo existente esté marcado como parcial, solo puede agregar métodos que aparezcan como como miembros del tipo existente a través de métodos de extensión. Como este es el caso, no puede agregar métodos estáticos al tipo en sí, ya que los métodos de extensión usan instancias de ese tipo.

No hay nada que nos impida la creación de su propio método de ayuda estático como sigue:

static class DateTimeHelper 
{ 
    public static DateTime Tomorrow 
    { 
     get { return DateTime.Now.AddDays(1); } 
    } 
} 

cual se utilizaría la siguiente manera:

DateTime tomorrow = DateTimeHelper.Tomorrow; 
+4

woot eh? a menos que se haya implementado dentro de los 6 meses posteriores a esto y la respuesta de [** Kumu **] (http://stackoverflow.com/a/1983396/274502) allí mismo, ¡parece realmente incompleto! – cregox

+2

@Cawas esto no está incompleto, Andrew muestra cómo hacer esto con un ayudante estático, no con un método de extensión (ya que no hay ninguna instancia). –

+0

Tienes razón, Nick. ¡Prefiero los métodos de extensión! ;) – cregox

15

Los métodos de extensión son azúcar sintáctica para la fabricación de los métodos estáticos cuyas primer parámetro es una instancia de buscar el tipo T como si se tratara de un método de instancia sobre T.

como tal, el beneficio se pierde en gran medida en la que permite hacer 'sta tic extension methods 'ya que servirían para confundir al lector del código incluso más que un método de extensión (ya que parecen estar completamente calificados pero no están realmente definidos en esa clase) para ninguna ganancia sintáctica (pudiendo encadenar llamadas en un estilo fluido dentro de Linq, por ejemplo).

Desde que tendría que llevar las extensiones en alcance con un uso de todos modos yo diría que es más sencillo y más seguro para crear:

public static class DateTimeUtils 
{ 
    public static DateTime Tomorrow { get { ... } } 
} 

y luego usar esto en su código a través de:

WriteLine("{0}", DateTimeUtils.Tomorrow) 
9

lo más cerca que puedo llegar a la respuesta es mediante la adición de un método de extensión en un objeto System.Type. No es bonito, pero sigue siendo interesante.

public static class Foo 
{ 
    public static void Bar() 
    { 
     var now = DateTime.Now; 
     var tomorrow = typeof(DateTime).Tomorrow(); 
    } 

    public static DateTime Tomorrow(this System.Type type) 
    { 
     if (type == typeof(DateTime)) { 
      return DateTime.Now.AddDays(1); 
     } else { 
      throw new InvalidOperationException(); 
     } 
    } 
} 

De lo contrario, IMO Andrew y ShuggyCoUk tiene una mejor implementación.

+0

Hay problemas con este enfoque. Tener que escribir "typeof (...)" no es conveniente, y con intellisense verá extensiones de cada tipo. Aún así, es un enfoque interesante en el que no había pensado, +1. –

+0

@ Meta-Knight Cierto, es por eso que personalmente prefiero la respuesta del otro. Mi respuesta tendría la sintaxis más cercana a la pregunta OP, pero no es la mejor manera de resolver este problema. –

+0

'Tipo' se puede reemplazar con cualquier otro tipo requerido. Lo uso con 'From' y funciona perfectamente. así que supongo que esta respuesta es general pero correcta – Katia

2

Por desgracia, no se puede hacer eso. Creo que sería útil, sin embargo. Es más natural al tipo:

DateTime.Tomorrow 

que:

DateTimeUtil.Tomorrow 

Con una clase Util, usted tiene que comprobar la existencia de un método estático en dos clases diferentes, en lugar de uno.

150

Utilice extension method.

Ex:

namespace ExtensionMethods 
{ 
    public static class MyExtensionMethods 
    { 
     public static DateTime Tomorrow(this DateTime date) 
     { 
      return date.AddDays(1); 
     }  
    } 
} 

Uso:

DateTime.Now.Tomorrow(); 

o

AnyObjectOfTypeDateTime.Tomorrow(); 
+2

[** Shuggy ** 's respuesta] (http://stackoverflow.com/a/1188276/274502) también triturar algo de luz en forma similar a la solución de esto. – cregox

+6

No olvides 'usar ExtensionMethods;' en la parte superior de su documento para esto. –

+0

¿por qué no puedo hacer DateTime.Tomorrow()? – lawphotog

3

yo haría lo mismo que kumu

namespace ExtensionMethods 
{ 
    public static class MyExtensionMethods 
    { 
     public static DateTime Tomorrow(this DateTime date) 
     { 
      return date.AddDays(1); 
     }  
    } 
} 

pero llámalo como este nuevo DateTime(). Mañana();

Creo que hace más seens que DateTime.Now.Tomorrow();

+1

¡Y se perdió la oportunidad de escribirlo como un comentario sobre la respuesta de Kumu! :PAG – cregox

3

Proporcionan la capacidad de extender los tipos existentes mediante la adición de nuevos métodos sin modificaciones necesarias para el tipo. Los métodos de llamada desde objetos del tipo extendido dentro de una aplicación utilizando la sintaxis del método de instancia se conocen como métodos de "extensión". Los métodos de extensión no son miembros de instancia en el tipo. El punto clave para recordar es que los métodos de extensión, definidos como métodos estáticos, están en el alcance solo cuando el espacio de nombres se importa explícitamente en el código fuente de la aplicación a través de la directiva using. Aunque los métodos de extensión se definen como métodos estáticos, todavía se llaman usando sintaxis de instancia.

Comprobar el ejemplo completo aquí http://www.dotnetreaders.com/articles/Extension_methods_in_C-sharp.net,Methods_in_C_-sharp/201

Ejemplo:

class Extension 
    { 
     static void Main(string[] args) 
     { 
      string s = "sudhakar"; 
      Console.WriteLine(s.GetWordCount()); 
      Console.ReadLine(); 
     } 

    } 
    public static class MyMathExtension 
    { 

     public static int GetWordCount(this System.String mystring) 
     { 
      return mystring.Length; 
     } 
    } 
3

que estaba buscando algo similar - una lista de restricciones de clases que proporcionan métodos de extensión. Parece difícil encontrar una lista concisa así que aquí va:

  1. no se puede tener cualquier cosa privada o protegida - campos, métodos, etc.

  2. Debe ser una clase estática, como en public static class... .

  3. Solo los métodos pueden estar en la clase, y todos deben ser públicos estáticos.

  4. No puede tener métodos estáticos convencionales; no se permiten aquellos que no incluyen este argumento.

  5. Todos los métodos deben comenzar:

    pública estática Tipo de retorno MethodName (Este nombre de clase _Es, ...)

Así que el primer argumento es siempre el presente referencia.

Hay un problema implícito que esto crea: si agrega métodos que requieren un bloqueo de cualquier tipo, realmente no puede proporcionarlo en el nivel de clase. Normalmente, proporcionaría un bloqueo de nivel de instancia privado, pero no es posible agregar ningún campo privado, lo que le deja con algunas opciones muy incómodas, como proporcionarlo como estática pública en alguna clase externa, etc. Se vuelve arriesgado. Signos the C# language had kind of a bad turn in the design for these.

La solución consiste en utilizar su clase de método de extensión como una fachada a una clase normal, y todos los métodos estáticos de la clase de extensión solo llaman a la clase real, probablemente usando a Singleton.

0

Hemos mejorado nuestra respuesta con detalle explanation.Now que es más fácil de entender sobre el método de extensión

Extension method: Es un mecanismo a través del cual podemos extender el comportamiento de la clase existente sin necesidad de utilizar la sub o classing modificando o recompilando la clase o estructura original.

Podemos extender nuestras clases personalizadas, clases de .NET Framework etc.

método de extensión

es en realidad un tipo especial de método estático que se define en la clase estática.

Como DateTime la clase ya está tomada arriba y por lo tanto no hemos tomado esta clase para la explicación.

A continuación se muestra el ejemplo

// Esta es una clase Calculadora existente, que tiene sólo un método (Añadir)

public class Calculator 
{ 
    public double Add(double num1, double num2) 
    { 
     return num1 + num2; 
    } 

} 

// Below is the extension class which have one extension method. 
public static class Extension 
{ 
    // It is extension method and it's first parameter is a calculator class.It's behavior is going to extend. 
    public static double Division(this Calculator cal, double num1,double num2){ 
     return num1/num2; 
    } 
} 

// We have tested the extension method below.   
class Program 
{ 
    static void Main(string[] args) 
    { 
     Calculator cal = new Calculator(); 
     double add=cal.Add(10, 10); 
     // It is a extension method in Calculator class. 
     double add=cal.Division(100, 10) 

    } 
} 
Cuestiones relacionadas