Es gab Fälle, in denen ich eine Methode in einer Klasse mit einer Erweiterungsmethode überschreiben wollte. Gibt es eine Möglichkeit, dies in C # zu tun?
Beispielsweise:
public static class StringExtension
{
public static int GetHashCode(this string inStr)
{
return MyHash(inStr);
}
}
Ein Fall, in dem ich dies tun wollte, besteht darin, einen Hash einer Zeichenfolge in einer Datenbank speichern zu können und denselben Wert von allen Klassen verwenden zu lassen, die den Hash der Zeichenfolgenklasse verwenden (z. B. Wörterbuch usw.) Es ist nicht garantiert, dass der integrierte .NET-Hashing-Algorithmus von einer Version des Frameworks zur nächsten kompatibel ist. Ich möchte ihn durch meine eigene ersetzen.
Es gibt andere Fälle, in denen ich eine Klassenmethode mit einer Erweiterungsmethode überschreiben möchte, damit sie nicht nur für die Zeichenfolgenklasse oder die GetHashCode-Methode spezifisch ist.
Ich weiß, dass ich dies mit einer Unterklasse einer vorhandenen Klasse tun könnte, aber es wäre in vielen Fällen praktisch, dies mit einer Erweiterung tun zu können.
quelle
Antworten:
Nein; Eine Erweiterungsmethode hat niemals Vorrang vor einer Instanzmethode mit einer geeigneten Signatur und nimmt niemals am Polymorphismus teil (
GetHashCode
ist einevirtual
Methode).quelle
.ToString()
in Arrays. Es ist definitiv eine notwendige Funktion.namespace System { public static class guilty { public static string ToLower(this string s) { return s.ToUpper() + " I'm Malicious"; } } }
Wenn die Methode eine andere Signatur hat, kann dies durchgeführt werden - also in Ihrem Fall: Nein.
Andernfalls müssen Sie die Vererbung verwenden, um das zu tun, wonach Sie suchen.
quelle
Soweit ich weiß, lautet die Antwort nein, da eine Erweiterungsmethode keine Instanz ist. Für mich ist es eher eine Intellisense-Funktion, mit der Sie eine statische Methode mit einer Instanz einer Klasse aufrufen können. Ich denke, eine Lösung für Ihr Problem kann ein Interceptor sein, der die Ausführung einer bestimmten Methode (z. B. GetHashCode ()) abfängt und etwas anderes tut. Um einen solchen Interceptor zu verwenden (wie der, den Castle Project bereitstellt), sollten alle Objekte mit einem instanziiert werden Object Factory (oder ein IoC-Container in Castle), damit ihre Schnittstellen über einen zur Laufzeit generierten dynamischen Proxy abgefangen werden können. (Mit Caslte können Sie auch virtuelle Mitglieder von Klassen abfangen.)
quelle
Ich habe einen Weg gefunden, eine Erweiterungsmethode mit derselben Signatur wie eine Klassenmethode aufzurufen, aber sie scheint nicht sehr elegant zu sein. Beim Herumspielen mit Erweiterungsmethoden bemerkte ich ein undokumentiertes Verhalten. Beispielcode:
Was mir auffiel, war, dass wenn ich eine zweite Methode innerhalb einer Erweiterungsmethode aufrief, diese die Erweiterungsmethode aufrief, die mit der Signatur übereinstimmte, selbst wenn es eine Klassenmethode gab, die auch mit der Signatur übereinstimmte. Wenn ich beispielsweise im obigen Code ExtFunc () aufrufe, das wiederum ele.GetDesc () aufruft, erhalte ich die Rückgabezeichenfolge "Extension GetDesc" anstelle der erwarteten Zeichenfolge "Base GetDesc".
Testen des Codes:
Auf diese Weise können Sie nach Belieben zwischen Klassenmethoden und Erweiterungsmethoden hin- und herwechseln, müssen jedoch doppelte "Pass-Through" -Methoden hinzufügen, um in den gewünschten "Bereich" zu gelangen. Ich nenne es hier Spielraum, weil es kein besseres Wort gibt. Hoffentlich kann mich jemand wissen lassen, wie es eigentlich heißt.
Vielleicht haben Sie anhand meiner "Pass-Through" -Methodennamen erraten, dass ich auch mit der Idee gespielt habe, Delegierte an sie weiterzugeben, in der Hoffnung, dass eine oder zwei Methoden als Pass-Through für mehrere Methoden mit derselben Signatur fungieren könnten. Leider sollte es nicht so sein, dass der Delegat nach dem Entpacken immer die Klassenmethode gegenüber der Erweiterungsmethode auswählte, selbst innerhalb einer anderen Erweiterungsmethode. "Umfang" spielte keine Rolle mehr. Ich habe Action- und Func-Delegierte allerdings nicht sehr oft eingesetzt, sodass vielleicht jemand mit mehr Erfahrung diesen Teil herausfinden könnte.
quelle