Il y a eu des occasions où je voudrais remplacer une méthode dans une classe avec une méthode d'extension. Existe-t-il un moyen de le faire en C #?
Par exemple:
public static class StringExtension
{
public static int GetHashCode(this string inStr)
{
return MyHash(inStr);
}
}
Un cas où j'ai voulu faire cela est de pouvoir stocker un hachage d'une chaîne dans une base de données et que cette même valeur soit utilisée par toutes les classes qui utilisent le hachage de la classe de chaîne (c'est-à-dire Dictionary, etc.) L'algorithme de hachage .Net intégré n'est pas garanti pour être compatible d'une version du Framework à l'autre, je souhaite le remplacer par le mien.
Il y a un autre cas dans lequel je voudrais remplacer une méthode de classe avec une méthode d'extension afin qu'il ne soit pas seulement spécifique à la classe de chaîne ou à la méthode GetHashCode.
Je sais que je pourrais le faire en sous-classant une classe existante, mais ce serait pratique de pouvoir le faire avec une extension dans de nombreux cas.
la source
Réponses:
Non; une méthode d'extension n'a jamais priorité sur une méthode d'instance avec une signature appropriée, et ne participe jamais au polymorphisme (
GetHashCode
c'est unevirtual
méthode).la source
.ToString()
dans les tableaux. C'est certainement une fonctionnalité nécessaire.namespace System { public static class guilty { public static string ToLower(this string s) { return s.ToUpper() + " I'm Malicious"; } } }
Si la méthode a une signature différente, cela peut être fait - donc dans votre cas: non.
Mais sinon, vous devez utiliser l'héritage pour faire ce que vous recherchez.
la source
Autant que je sache, la réponse est non, car une méthode d'extension n'est pas une instance, c'est plutôt une fonction intellisense qui vous permet d'appeler une méthode statique en utilisant une instance d'une classe. Je pense qu'une solution à votre problème peut être un intercepteur qui intercepte l'exécution d'une méthode spécifique (par exemple GetHashCode ()) et fait autre chose.Pour utiliser un tel intercepteur (comme celui fourni par Castle Project), tous les objets doivent être instansiés à l'aide d'un object factory (ou un conteneur IoC dans Castle) afin que leurs interfaces puissent être interceptées via un proxy dynamique généré au runtime (Caslte vous permet également d'intercepter les membres virtuels des classes)
la source
J'ai trouvé un moyen d'invoquer une méthode d'extension avec la même signature qu'une méthode de classe, mais cela ne semble pas très élégant. En jouant avec les méthodes d'extension, j'ai remarqué un comportement non documenté. Exemple de code:
Ce que j'ai remarqué, c'est que si j'appelais une deuxième méthode à partir d'une méthode d'extension, elle appellerait la méthode d'extension qui correspondait à la signature même s'il y avait une méthode de classe qui correspondait également à la signature. Par exemple dans le code ci-dessus, lorsque j'appelle ExtFunc (), qui à son tour appelle ele.GetDesc (), j'obtiens la chaîne de retour "Extension GetDesc" au lieu de la chaîne "Base GetDesc" que nous attendons.
Tester le code:
Cela vous permet de rebondir entre les méthodes de classe et les méthodes d'extension à volonté, mais nécessite l'ajout de méthodes "pass-through" en double pour vous amener dans la "portée" que vous désirez. J'appelle cela portée ici faute d'un meilleur mot. J'espère que quelqu'un pourra me dire comment cela s'appelle réellement.
Vous avez peut-être deviné par mes noms de méthodes «pass-through» que j'ai aussi caressé l'idée de leur passer des délégués dans l'espoir qu'une seule méthode ou deux puisse agir comme un relais pour plusieurs méthodes avec la même signature. Malheureusement, ce n'était pas comme une fois que le délégué a été décompressé, il a toujours choisi la méthode de classe plutôt que la méthode d'extension, même à partir d'une autre méthode d'extension. "Portée" n'avait plus d'importance. Cependant, je n'ai pas beaucoup utilisé les délégués Action et Func, alors peut-être que quelqu'un de plus expérimenté pourrait comprendre cette partie.
la source