multiple - ¿Hay alguna forma de llamar a la versión principal de un método reemplazado?(C#.NET)
inherits c# asp net (8)
En el siguiente código probé de dos maneras para acceder a la versión principal de methodTwo, pero el resultado siempre fue 2. ¿Hay alguna forma de obtener el 1 resultado de una instancia de ChildClass sin modificar estas dos clases?
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();
}
}
Actualizar ChrisW publicó esto:
Desde fuera de la clase, no sé de ninguna manera fácil; pero, tal vez, no sé qué sucede si intentas la reflexión: utiliza el método Type.GetMethod para encontrar el MethodInfo asociado con el método en ParentClass, y luego llama a MethodInfo.Invoke
Esa respuesta fue eliminada. Me pregunto si ese hack podría funcionar, solo por curiosidad.
Como dijo Mark Gravell, no, no externamente. Pero aquí hay otro truco que he usado. ChildClass
puede exponer methodTwo()
de ParentClass
para su propio uso o para uso externo. En tu caso:
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());
En mi caso, la clase infantil introdujo el concepto de un Peer, y necesitaba su anulación de methodTwo()
para invocar la versión base en el peer. Al anularlo, sin embargo, lo ocultó ... ¿O sí? Esta técnica vino al rescate.
class ChildClass : ParentClass {
ChildClass peer;
override public int methodTwo() {
return peer.ParentClass_methodTwo();
}
private int ParentClass_methodTwo() {
return base.methodTwo();
}
}
Como se mencionó anteriormente, algo es malo con el diseño de su clase si necesita llamar a "base.base" en el código de PRODUCCIÓN. Pero es bastante legítimo utilizar esta técnica si está depurando o buscando algún workarrounds mientras usa bibliotecas externas que no puede compilar. Es desagradable que C # no proporcione esta opción directamente. Aún puede usar la solución Kenneth Xu con generador de IL y Emitir. Funciona.
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 });
Para referencia y una muestra completa, vea http://kennethxu.blogspot.cz/2009/05/cnet-calling-grandparent-virtual-method.html
Gracias Kenneth Xu!
Dentro de ChildClass.methodTwo()
, puedes llamar a base.methodTwo()
.
Fuera de la clase, la llamada ((ParentClass)a).methodTwo())
llamará a ChildClass.methodTwo
. Esa es la razón por la cual existen métodos virtuales.
En el nivel IL, probablemente podría emitir una call
lugar de una call
callvirt
, y hacer el trabajo, pero si nos limitamos a C # ;-p ( edit maldito! El tiempo de ejecución lo detiene: VerificationException
: "La operación podría desestabilizar el tiempo de ejecución. "; eliminar lo virtual
y funciona bien, demasiado inteligente a la mitad ...)
Dentro del tipo ChildClass
, puede usar base.methodTwo()
; sin embargo, esto no es posible de forma externa. Tampoco puedes bajar más de un nivel: no hay base.base.Foo()
.
Sin embargo, si deshabilita el polimorfismo utilizando el método de ocultación, puede obtener la respuesta que desee, pero por malas razones:
class ChildClass : ParentClass
{
new public int methodTwo() // bad, do not do
{
return 2;
}
}
Ahora puede obtener una respuesta diferente del mismo objeto dependiendo de si la variable está definida como una ChildClass
o una ParentClass
.
Me encontré con esto en busca de ayuda y terminé con mi propio enfoque para llamar a las versiones ancestrales de un método. Esto es más una solución que supone que puede editar la clase ancestra:
Ponga la funcionalidad en cuestión en la clase antecesora en un método estático, con los parámetros necesarios. El método en esa clase puede llamarlo para que no necesite duplicar la funcionalidad, y la clase hija puede llamar a esa funcionalidad si lo desea a través del método estático. De esta manera, se puede hacer incluso dentro de un método y puede citar qué clase específica quiere invocar. Además, puede acceder a antepasados más lejanos que los meros padres, que es la limitación de uso "base".
Pensaría que no es posible a menos que haga una instancia de ParentClass directamente. Esa es la verdadera esencia de la herencia, el polimorfismo ...
Que yo sepa, una vez que un método ha sido anulado, entonces no puede llamar al método principal.
public class Parent
{
public string Method()
{
return "parent";
}
}
public class Child:Parent
{
public string Method()
{
return "child";
}
}
El código anterior anula exitosamente el método padre pero el valor del método padre aún no se ha modificado.
Puede devolver valores de la clase Both Parent y de la clase Child usando el siguiente código:
Child child = new Child();
string result = (((Parent)child).Method()) + child.Method();
Pero Visual Studio le mostrará una advertencia en Tiempo de compilación.