2010-06-15 22 views
65

En cuanto a algunos ejemplos de código para HtmlHelper, y veo las declaraciones que se parecen:"este" en el parámetro de la función

public static string HelperName(this HtmlHelper htmlHelper, ...more regular params) 

No puedo recordar haber visto este tipo de constructo en ninguna otra parte - alguien puede explicar la propósito del "esto"? Pensé que al declarar algo público estático significaba que la clase no necesitaba ser instanciada, entonces, ¿qué es "esto" en este caso?

Respuesta

162

Esta es la sintaxis para declarar métodos de extensión, una nueva característica de C# 3.0.

Un método de extensión es código de pieza, compilador de piezas "mágico", donde el compilador con la ayuda de intellisense en Visual Studio hace que parezca que su método de extensión está realmente disponible como un método de instancia en el objeto en cuestión.

Déjeme dar un ejemplo.

No hay método en la clase String que se nombra GobbleGobble, por lo que vamos a crear un método de extensión:

public static class StringExtensions 
{ 
    public static void GobbleGobble(this string s) 
    { 
     Console.Out.WriteLine("Gobble Gobble, " + s); 
    } 
} 

El nombre de la clase es sólo mi convención de nombres, no es necesario darle un nombre como ese, pero tiene que ser estático, al igual que el método.

Después de declarar el método anterior, se puede, en Visual Studio, escriba lo siguiente:

String s = "Turkey Baster!"; 
s. 

después del punto, esperar a que IntelliSense, y notar que hay un método GobbleGobble allí, completar el código como el siguiente:

String s = "Turkey Baster!"; 
s.GobbleGobble(); 

Importante: la clase en la que se declara el método de extensión debe estar disponible para el compilador y el procesador intelisense con el fin de intelliSense para mostrar el método. Si escribe GobbleGobble manualmente, y usa Ctrl + . atajo, no le ayudará a obtener el derecho de usar directivas en el archivo.

Observe que el parámetro del método ha desaparecido. El compilador silenciosamente moverse por las partes importantes, que son:

String s = "Turkey Baster!"; 
s.GobbleGobble(); 
^ ^
|  +-- the compiler will find this in the StringExtensions class 
| 
+-- will be used as the first parameter to the method 

Por lo tanto, el código anterior será transformada por el compilador para esto:

String s = "Turkey Baster!"; 
StringExtensions.GobbleGobble(s); 

Así que en llamadas en tiempo, no hay nada mágico al respecto, es solo una llamada a un método estático.

Tenga en cuenta que si su método de extensión declara más de un parámetro, sólo la primera soporta el modificador this, y el resto tiene que ser especificado como parte de la llamada al método como normales:

public static void GobbleGobble(this string value, string extra) 
{           |    | 
    ...          |    | 
}           |    | 
              |    | 
+--------------------------------------------+    | 
|               | 
v               | 
s.GobbleGobble("extra goes here");       | 
         ^         | 
         |         | 
         +-----------------------------------+ 

Los métodos de extensión fue agregado en parte debido a Linq, donde la sintaxis Linq de C# buscará métodos de extensión apropiadamente nombrados para los objetos en juego, lo que significa que usted puede "presentar" Linq-support en cualquier tipo de clase simplemente declarando los métodos de extensión correctos. Por supuesto, el soporte completo de Linq es mucho trabajo, pero es posible.

Además, los métodos de extensión en sí mismos son realmente útiles, así que lea sobre él.

He aquí algunos enlaces:

+2

Pish tosh, no deberías contestar de todos modos, ¡ya deberías estar haciéndome un buen editor de diagramas! :) (ah, y gracias por la clase de alabanza señor!) –

+2

Definitivamente voy a comenzar a usar el término "engullir engullir magia". – chris

+0

Youtube rompió el enlace nuevamente, http://www.youtube.com/watch?v=Bz_heb9Rz2g, aún en @ 1: 00 en adelante. –

6

Se utiliza para los métodos de extensión. Básicamente, usted 'pegamento' la Helpername al objeto HtmlHelper por lo que se puede decir:

new HtmlHelper().HelperName(...more regular params); 
4

Eso sería un método de extensión. Le permiten "extender" una clase a través de métodos estáticos que viven fuera de la clase original.

Por ejemplo, supongamos que tiene un método de cadena muy útil que se utiliza todo el tiempo ...

public int CountAllAs(string orig) 
{ 
    return orig.ToLowerInvariant().ToArray().Count(c => c == 'a'); 
} 

Y llamarlo ...

string allAs = "aaaA"; 
int count = CountAllAs(allAs); 

que no es demasiado malo. Pero con un pequeño cambio, podría hacer que un método de extensión y la llamada sería un poco más bonita:

public static int CountAllAs(this string orig) 
{ 
    return orig.ToLowerInvariant().ToArray().Count(c => c == 'a'); 
} 

Y luego llamarlo ...

string allAs = "aaaA"; 
int count = allAs.CountAllAs(); 
3

Extensions Methods ...

... es una manera fantástica de incluir funciones como si utilizara el decorator pattern, pero sin el esfuerzo de refactorizar todo su código o usar un nombre diferente de un tipo común.

public static class Extensions 
{ 
    public static string RemoveComma(this string value) 
    { 
     if (value == null) throw new ArgumentNullException("value"); 
     return value.Replace(",", ""); 
    } 
} 

Para que pueda usar este código, en cualquier lugar de su aplicación.

Console.WriteLine(“Hello, My, Friend”.RemoveComma()) 

>> Hello My Friend 

Así que la este comando atribuyen significar el tipo que la extensión será “agregado”, y le permiten trabajar con el valor que si se pasa como parámetro.

6

Después métodos de extensión, he estado usando como un loco .. aquí es de unos pocos utilizo constantemente ..

public static T ChangeType<T>(this object obj) 
{ 
    return (T)Convert.ChangeType(obj, typeof(T)); 
} 

funciona de la siguiente ..

int i = "123".ChangeType<int>(); 
bool valid = "bool".ChangeType<bool>(); 
int id = dataSet.Tables[0].Rows[0]["Id"].ChangeType<int>(); 

Sí, aparece en cada objeto, puede ser molesto, pero desde que lo uso para prácticamente cada tipo de datos, ayuda a péguelo simplemente un objeto en lugar de duplicarla para cada tipo de datos posible.

public static string ToXml(this object serializableObject) 
{ 
    var aMemStr = new MemoryStream(); 
    try 
    { 
     var serializer = new XmlSerializer(serializableObject.GetType()); 
     serializer.Serialize(new XmlTextWriter(aMemStr, null), serializableObject); 
     return Encoding.UTF8.GetString(aMemStr.ToArray()); 
    } 
    finally { if (aMemStr != null) { aMemStr.Dispose(); } } 
} 

string xml = dataSet.ToXml(); 

public static T ToObject<T>(this string xmlString) 
{ 
    var aStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString)); 
    try { return (T)new XmlSerializer(typeof(T)).Deserialize(aStream); } 
    finally { if (aStream != null) { aStream.Dispose(); aStream = null; } } 
} 

DataSet dataSet = xml.ToObject<DataSet>(); 
Cuestiones relacionadas