Czy istnieje sposób wywołania wersji nadrzędnej zastępowanej metody? (C # .Net)


W poniższym kodzie próbowałem uzyskać dostęp do wersji nadrzędnej metody methodTwo na dwa sposoby, ale wynik zawsze wynosił 2. Czy istnieje sposób uzyskania wyniku 1 z instancji ChildClass bez zmiany tych dwóch klas?
class ParentClass
{
public int methodOne()
{
return methodTwo();
} virtual public int methodTwo()
{
return 1;
}
}class ChildClass : ParentClass
{
override public int methodTwo()
{
return 2;
}
}class Program
{
static void Main(string[] args)
{
var a = new ChildClass();
Console.WriteLine("a.methodOne(): " + a.methodOne());
Console.WriteLine("a.methodTwo(): " + a.methodTwo());
Console.WriteLine("((ParentClass)a).methodTwo(): "
+ ((ParentClass)a).methodTwo());
Console.ReadLine();
}
}


Update

ChrisW opublikował to:

Poza klasą, nie wiem
niełatwy sposób; ale może nie jestem
wiesz, co się stanie, jeśli spróbujesz
refleksja: użyj
metoda Type.GetMethod, aby znaleźć MethodInfo,
skojarzone z metodą w klasie.
ParentClass, a następnie zadzwoń
MethodInfo.Invoke

Ta odpowiedź została usunięta. Zastanawiam się, czy ten hack może zadziałać, tylko z ciekawości.
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Wewnątrz
ChildClass.methodTwo ()
możesz wywołać
base.methodTwo ()
.
Poza klasą wywołanie
((ParentClass) a) .methodTwo ()


wywoła
ChildClass.methodTwo
. To jest cały powód istnienia metod wirtualnych.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Na poziomie IL prawdopodobnie mógłbyś wywołać
call
zamiast
callvirt
i wykonać zadanie - ale jeśli jesteśmy ograniczeni do C #; - p (

edit

cerować! środowisko wykonawcze zatrzymuje Cię:
VerificationException
: "operacja może zdestabilizować środowisko wykonawcze"; usuń
virtual
i działa dobrze; za sprytny o połowę ...)
Wewnątrz typu
ChildClass
możesz użyć
base.methodTwo ()
- jednak nie jest to możliwe z zewnątrz. Nie możesz też zejść o więcej niż jeden poziom - nie ma wsparcia dla
base.base.Foo ()
.
Jeśli jednak wyłączysz polimorfizm metodą ukrywania, możesz uzyskać pożądany

odpowiedź

ale ze złych powodów:
class ChildClass : ParentClass
{
new public int methodTwo()// bad, do not do
{
return 2;
}
}

Możesz teraz uzyskać inną odpowiedź z tego samego obiektu w zależności od tego, czy zmienna jest zdefiniowana jako
ChildClass
czy
ParentClass
.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jak wspomniano powyżej, coś jest nie tak z projektem twojej klasy, jeśli musisz wywołać "base.base" w kodzie PRODUCTION. Ale użycie tej metody jest całkowicie legalne, jeśli debugujesz lub szukasz obejść w przypadku korzystania z bibliotek zewnętrznych, których nie możesz skompilować. To frustrujące, że C # nie udostępnia tej opcji bezpośrednio. Możesz jednak użyć rozwiązania Kennetha Xu z generatorem IL i emitować. To działa.
class A { public virtual string foo() { return "A"; } }class B : A { public override string foo() { return "B"; } }// now in class C
class C : B {}
// we can call virtual method "foo" from A using following code
MethodInfo fooA = typeof(A).GetMethod("foo", BindingFlags.Public | BindingFlags.Instance);DynamicMethod baseBaseFoo = new DynamicMethod( "foo_A",
typeof(string),
new[] { typeof(A) },
typeof(A));
ILGenerator il = baseBaseFoo.GetILGenerator();
il.Emit(OpCodes.Ldarg, 0);
il.EmitCall(OpCodes.Call, fooA, null);
il.Emit(OpCodes.Ret);// call foo() from class A, it returns "A"
(string)baseBaseFoo.Invoke(null, new object[] { this });

Aby uzyskać więcej informacji i pełną próbkę, zobacz

http://kennethxu.blogspot.cz/2009/05/ site cnet-Calls-grandpa-virtual-method.html
http://kennethxu.blogspot.cz/2 ... .html
Dziękuję Kenneth Xu!
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jak powiedział Mark Gravell, nie, nie na zewnątrz. Ale oto kolejny hack, którego użyłem.
ChildClass
może ujawnić
methodTwo ()
z
ParentClass
do użytku własnego lub zewnętrznego. W Twoim przypadku:
class ChildClass : ParentClass {
override public int methodTwo() {
return 2;
}
public int ParentClass_methodTwo() {
return base.methodTwo();
}
}// Now instead of
Console.WriteLine("ParentClass methodTwo: " + ((ParentClass)a).methodTwo());
// use
Console.WriteLine("ParentClass methodTwo: " + a.ParentClass_methodTwo());

W moim przypadku klasa potomna wprowadziła koncepcję peera i musiałem nadpisać ją za pomocą
methodTwo ()
, aby wywołać wersję podstawową na peerze. Jednak odrzucając to, ukrył to ... A może tak? Ta technika przyszła na ratunek.
class ChildClass : ParentClass {
ChildClass peer;
override public int methodTwo() {
return peer.ParentClass_methodTwo();
}
private int ParentClass_methodTwo() {
return base.methodTwo();
}
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

public class Parent 
{
public string Method()
{
return "parent"; }
}public class Child:Parent
{
public string Method()
{
return "child"; }
}

Powyższy kod pomyślnie zastępuje metodę nadrzędną, ale wartość metody nadrzędnej pozostaje niezmieniona.
Możesz zwrócić wartości z obu

klasa rodzicielska

i od

klasa podrzędna

używając poniższego kodu -
Child child = new Child();
string result = (((Parent)child).Method()) + child.Method();
Ale program Visual Studio wyświetli ostrzeżenie w czasie kompilacji.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

O ile wiem, po nadpisaniu metody nie można wywołać metody nadrzędnej.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Wydaje mi się, że nie jest to możliwe, chyba że bezpośrednio utworzysz instancję ParentClass.
To jest istota dziedziczenia, polimorfizm ...
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Natknąłem się na to, szukając pomocy, i ostatecznie znalazłem swoje własne podejście do wywoływania przodków metody. Jest to raczej obejście, które zakłada, że ​​możesz edytować klasę nadrzędną:
Umieść odpowiednią funkcjonalność w klasie nadrzędnej w metodzie statycznej z wymaganymi parametrami. Metoda w tej klasie może ją wywołać, więc nie musi powielać funkcji, a klasa potomna może wywołać tę funkcję, jeśli to konieczne, za pomocą metody statycznej. Można więc to zrobić nawet wewnątrz metody i określić, którą konkretną klasę chce wywołać. Ponadto może mieć dostęp do przodków bardziej odległych niż tylko rodzice, co jest ograniczeniem w używaniu słowa „baza”.

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się