Ha habido ocasiones en las que me gustaría anular un método en una clase con un método de extensión. ¿Hay alguna forma de hacer eso en C #?
Por ejemplo:
public static class StringExtension
{
public static int GetHashCode(this string inStr)
{
return MyHash(inStr);
}
}
Un caso en el que he querido hacer esto es poder almacenar un hash de una cadena en una base de datos y hacer que el mismo valor sea utilizado por todas las clases que usan el hash de la clase de cadena (es decir, Diccionario, etc.) No se garantiza que el algoritmo hash .Net incorporado sea compatible de una versión del Framework a la siguiente, quiero reemplazarlo por el mío.
Hay otro caso con el que me he encontrado en el que también me gustaría anular un método de clase con un método de extensión, por lo que no es solo específico de la clase de cadena o el método GetHashCode.
Sé que podría hacer esto con subclases de una clase existente, pero sería útil poder hacerlo con una extensión en muchos casos.
fuente
Respuestas:
No; un método de extensión nunca tiene prioridad sobre un método de instancia con una firma adecuada y nunca participa en el polimorfismo (
GetHashCode
es unvirtual
método).fuente
.ToString()
en matrices. Definitivamente es una característica necesaria.namespace System { public static class guilty { public static string ToLower(this string s) { return s.ToUpper() + " I'm Malicious"; } } }
Si el método tiene una firma diferente, entonces se puede hacer, así que en su caso: no.
Pero de lo contrario, debe usar la herencia para hacer lo que está buscando.
fuente
Hasta donde yo sé, la respuesta es no, porque un método de extensión no es una instancia, para mí es más como una función intellisense que te permite llamar a un método estático usando una instancia de una clase. Creo que una solución a su problema puede ser un interceptor que intercepte la ejecución de un método específico (por ejemplo, GetHashCode ()) y haga otra cosa. Para usar un interceptor de este tipo (como el que proporciona Castle Project), todos los objetos deben instalarse usando un fábrica de objetos (o un contenedor de IoC en Castle) para que sus interfaces puedan ser interceptadas a través de un proxy dinámico generado en tiempo de ejecución (Caslte también le permite interceptar miembros virtuales de clases)
fuente
He encontrado una forma de invocar un método de extensión con la misma firma que un método de clase, sin embargo, no parece muy elegante. Al jugar con los métodos de extensión, noté un comportamiento indocumentado. Código de muestra:
Lo que noté fue que si llamaba a un segundo método desde dentro de un método de extensión, llamaría al método de extensión que coincidía con la firma, incluso si había un método de clase que también coincidía con la firma. Por ejemplo, en el código anterior, cuando llamo a ExtFunc (), que a su vez llama a ele.GetDesc (), obtengo la cadena de retorno "Extension GetDesc" en lugar de la cadena "Base GetDesc" que esperaríamos.
Probando el código:
Esto le permite ir y venir entre métodos de clase y métodos de extensión a voluntad, pero requiere la adición de métodos de "paso a través" duplicados para llegar al "alcance" que desea. Lo llamo alcance aquí a falta de una palabra mejor. Espero que alguien me pueda decir cómo se llama realmente.
Es posible que haya adivinado por los nombres de mis métodos de "paso a través" que también jugué con la idea de pasarles delegados con la esperanza de que uno o dos métodos pudieran actuar como un paso para varios métodos con la misma firma. Desafortunadamente, no fue así, ya que una vez que se descomprimió el delegado, siempre eligió el método de clase sobre el método de extensión, incluso desde dentro de otro método de extensión. El "alcance" ya no importaba. Sin embargo, no he usado mucho a los delegados de Action y Func, así que tal vez alguien con más experiencia pueda resolver esa parte.
fuente