Houve ocasiões em que eu desejaria substituir um método em uma classe por um método de extensão. Existe alguma maneira de fazer isso em C #?
Por exemplo:
public static class StringExtension
{
public static int GetHashCode(this string inStr)
{
return MyHash(inStr);
}
}
Um caso em que eu queria fazer isso é ser capaz de armazenar um hash de uma string em um banco de dados e fazer com que o mesmo valor seja usado por todas as classes que usam o hash da classe de string (isto é, Dicionário, etc.). O algoritmo de hashing .Net integrado não tem garantia de compatibilidade de uma versão do Framework para a próxima, desejo substituí-lo pela minha.
Há outro caso que encontrei em que também gostaria de substituir um método de classe por um método de extensão, portanto, não é apenas específico para a classe de string ou o método GetHashCode.
Eu sei que poderia fazer isso com a subclasse de uma classe existente, mas seria útil poder fazer isso com uma extensão em muitos casos.
fonte
Respostas:
Não; um método de extensão nunca tem prioridade sobre um método de instância com uma assinatura adequada e nunca participa de polimorfismo (
GetHashCode
é umvirtual
método).fonte
.ToString()
em matrizes. Definitivamente, é um recurso necessário.namespace System { public static class guilty { public static string ToLower(this string s) { return s.ToUpper() + " I'm Malicious"; } } }
Se o método tiver uma assinatura diferente, isso pode ser feito - no seu caso: não.
Caso contrário, você precisará usar herança para fazer o que está procurando.
fonte
Pelo que eu sei, a resposta é não, porque um método de extensão não é uma instância. É mais como um recurso do intellisense para mim que permite chamar um método estático usando uma instância de uma classe. Acho que uma solução para o seu problema pode ser um interceptor que intercepte a execução de um método específico (por exemplo, GetHashCode ()) e faça outra coisa. Para usar tal interceptor (como o fornecido pelo Castle Project), todos os objetos devem ser instanciados usando um fábrica de objetos (ou um contêiner IoC em Castle) para que suas interfaces possam ser interceptadas por meio de um proxy dinâmico gerado em tempo de execução. (Caslte também permite interceptar membros virtuais de classes)
fonte
Eu descobri uma maneira de invocar um método de extensão com a mesma assinatura de um método de classe, mas não parece muito elegante. Ao brincar com os métodos de extensão, notei alguns comportamentos não documentados. Código de amostra:
O que percebi foi que, se chamasse um segundo método de dentro de um método de extensão, ele chamaria o método de extensão que correspondia à assinatura, mesmo que houvesse um método de classe que também correspondesse à assinatura. Por exemplo, no código acima, quando chamo ExtFunc (), que por sua vez chama ele.GetDesc (), obtenho a string de retorno "Extension GetDesc" em vez da string "Base GetDesc" que esperaríamos.
Testando o código:
Isso permite que você alterne entre métodos de classe e métodos de extensão à vontade, mas requer a adição de métodos de "passagem" duplicados para chegar ao "escopo" desejado. Estou chamando de escopo aqui por falta de uma palavra melhor. Espero que alguém possa me informar como realmente se chama.
Você deve ter adivinhado por meus nomes de método de "passagem" que também brinquei com a ideia de passar delegados para eles na esperança de que um único método ou dois pudessem atuar como passagem para vários métodos com a mesma assinatura. Infelizmente, não deveria ser assim, uma vez que o delegado era descompactado, ele sempre escolhia o método de classe em vez do método de extensão, mesmo dentro de outro método de extensão. "Escopo" não importava mais. Eu não usei delegados Action e Func muito embora, então talvez alguém mais experiente possa descobrir essa parte.
fonte