Zdarzały się sytuacje, w których chciałbym przesłonić metodę w klasie z metodą rozszerzającą. Czy jest jakiś sposób, aby to zrobić w C #?
Na przykład:
public static class StringExtension
{
public static int GetHashCode(this string inStr)
{
return MyHash(inStr);
}
}
Przykładem, w którym chciałem to zrobić, jest możliwość przechowywania skrótu ciągu w bazie danych i posiadania tej samej wartości, która będzie używana przez wszystkie klasy, które używają skrótu klasy ciągu (np. Dictionary itp.). nie ma gwarancji, że wbudowany algorytm haszowania .Net będzie kompatybilny z jedną wersją Framework do następnej, chcę go zastąpić własną.
Są inne przypadki, z którymi się spotkałem, w których chciałbym zastąpić metodę klasy metodą rozszerzającą, więc nie jest ona specyficzna tylko dla klasy string lub metody GetHashCode.
Wiem, że mógłbym to zrobić z podklasą istniejącej klasy, ale w wielu przypadkach byłoby przydatne móc to zrobić z rozszerzeniem.
źródło
Odpowiedzi:
Nie; metoda rozszerzająca nigdy nie ma pierwszeństwa przed metodą instancji z odpowiednim podpisem i nigdy nie uczestniczy w polimorfizmie (
GetHashCode
jestvirtual
metodą).źródło
.ToString()
W tablicach. Jest to zdecydowanie potrzebna funkcja.namespace System { public static class guilty { public static string ToLower(this string s) { return s.ToUpper() + " I'm Malicious"; } } }
Jeśli metoda ma inny podpis, to można to zrobić - czyli w Twoim przypadku: nie.
Ale w przeciwnym razie musisz użyć dziedziczenia, aby zrobić to, czego szukasz.
źródło
O ile wiem, odpowiedź brzmi: nie, ponieważ metoda rozszerzająca nie jest instancją, a dla mnie bardziej przypomina funkcję Intellisense, która pozwala wywołać metodę statyczną przy użyciu instancji klasy. Myślę, że rozwiązaniem twojego problemu może być przechwytywacz, który przechwytuje wykonanie określonej metody (np. GetHashCode ()) i zrobi coś innego. Aby użyć takiego przechwytywacza (takiego jak ten, który zapewnia Castle Project), wszystkie obiekty powinny być instansowane za pomocą fabryka obiektów (lub kontener IoC w Castle), dzięki czemu ich interfejsy mogą być przechwytywane przez dynamiczne proxy generowane w czasie wykonywania (Caslte umożliwia również przechwytywanie wirtualnych członków klas)
źródło
Znalazłem sposób na wywołanie metody rozszerzającej z taką samą sygnaturą jak metoda klasowa, jednak nie wydaje się ona zbyt elegancka. Podczas zabawy z metodami rozszerzającymi zauważyłem nieudokumentowane zachowanie. Przykładowy kod:
Zauważyłem, że gdybym wywołał drugą metodę z wnętrza metody rozszerzającej, wywołałaby metodę rozszerzenia, która pasowała do podpisu, nawet jeśli istniałaby metoda klasy, która również pasuje do podpisu. Na przykład w powyższym kodzie, kiedy wywołuję ExtFunc (), który z kolei wywołuje ele.GetDesc (), otrzymuję zwrotny ciąg znaków „Extension GetDesc” zamiast ciągu „Base GetDesc”, którego byśmy się spodziewali.
Testowanie kodu:
Pozwala to na dowolne przechodzenie między metodami klas i metodami rozszerzającymi, ale wymaga dodania zduplikowanych metod „przekazujących”, aby uzyskać pożądany „zakres”. Nazywam to zakresem z braku lepszego słowa. Mam nadzieję, że ktoś może mi powiedzieć, jak to się właściwie nazywa.
Mogłeś odgadnąć na podstawie moich nazw metod „tranzytowych”, którymi również bawiłem się pomysłem przekazywania im delegatów w nadziei, że jedna lub dwie metody mogą działać jako przejście dla wielu metod z tym samym podpisem. Niestety nie miało to być tak, że po rozpakowaniu delegata zawsze wybierał metodę klasy zamiast metody rozszerzającej, nawet z wnętrza innej metody rozszerzającej. „Zakres” nie miał już znaczenia. Nie korzystałem zbytnio z delegatów Action i Func, więc może ktoś bardziej doświadczony mógłby to rozgryźć.
źródło