How to use reflection call a base method that is overridden by derived class?
class Base
{
public virtual void Foo() { Console.WriteLine("Base"); }
}
class Derived : Base
{
public override void Foo() { Console.WriteLine("Derived"); }
}
public static void Main()
{
Derived d = new Derived();
typeof(Base).GetMethod("Foo").Invoke(d, null);
Console.ReadLine();
}
This code always shows 'Derived'...
After a long time, I finally find a better solution than DynamicMethod:
class CallOverride
{
public static void Test()
{
var obj = new Override();
var method = typeof(object).GetMethod("ToString");
var ftn = method.MethodHandle.GetFunctionPointer();
var func = (Func<string>)Activator.CreateInstance(typeof(Func<string>), obj, ftn);
Console.WriteLine(func());
}
}
class Override
{
public override string ToString()
{
return "Nope";
}
}
This solution use the standard constructor signature of delegate:
public Delegate(object target, IntPtr ftn)
where target is the target instance and ftn is the function pointer.
It directly invoke it with the function pointer of base method, so the delegate will point to the actual base method, not the overridden method.
Even though the current answer is already accepted, it's actually possible without having to change the original class by using a dynamic method like this:
static void Main(string[] args)
{
Derived foo = new Derived();
foo.Foo();
MethodInfo method = typeof(Base).GetMethod("Foo");
DynamicMethod dm = new DynamicMethod("BaseFoo", null, new Type[] { typeof(Derived) }, typeof(Derived));
ILGenerator gen = dm.GetILGenerator();
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, method);
gen.Emit(OpCodes.Ret);
var BaseFoo = (Action<Derived>)dm.CreateDelegate(typeof(Action<Derived>));
BaseFoo(foo);
Console.ReadKey();
}
as you can see it's still relatively simple to do
This can be achieved through Code emit
http://blogs.msdn.com/b/rmbyers/archive/2008/08/16/invoking-a-virtual-method-non-virtually.aspx
You can't do that, even with reflection. Polymorphism in C# actually guarantees that Derived.Foo() will always be called, even on an instance of Derived cast back to its base class.
The only way to call Base.Foo() from a Derived instance is to explicitly make it accessible from the Derived class:
class Derived : Base
{
public override void Foo()
{
Console.WriteLine("Derived");
}
public void BaseFoo()
{
base.Foo();
}
}
Here is a general form of #Kii answer above:
// returns a delegate (of type methodType) that calls obj.base.method(..)
static object VirtualMethodBase(Type methodType, string methodName, Object obj) {
var method = obj.GetType().BaseType.GetMethod(methodName);
var ftn = method.MethodHandle.GetFunctionPointer();
return Activator.CreateInstance(methodType, obj, ftn);
}
usage:
public class Base {
public override string ToString() => "Base";
public virtual int F(int x, int y) => x+y;
}
public class Derived : Base {
public override string ToString() => "Derived";
public override int F(int x, int y) => x*y;
}
var b = new Base();
var d = new Derived();
var sb = b.ToString(); // "Base"
var fb = b.F(2, 3); // 5
var sd = d.ToString(); // "Derived"
var fd = d.F(2, 3); // 6
// obj.base.ToString()
static string ToStringBase(object obj) => ((Func<string>)VirtualMethodBase(typeof(Func<string>), "ToString", obj))();
// obj.base.F(x, y)
static int FBase(Base bobj, int x, int y) => ((Func<int, int, int>)VirtualMethodBase(typeof(Func<int, int, int>), "F", bobj))(x, y);
var sd1 = ToStringBase(d); // "Base"
var fd1 = FBase(d, 2, 3); // 5
What you are seeing is the polymorphic behaviour that is by design. When you override a virtual method, invoking that method on the overridden class calls the decendant class's implementation from the VMT.
What is your use case, to be honest this smells a little like a design problem.
Reflection allows you to see that the object d has a "Foo" method and also to invoke it.
This method however is a virtual method and that's why you're getting the implementation of that method by a Derived class since that is what d is (in addition to also being castable to a Base).
There is no [direct] way to invoke the Base's virtual methods from a Derived object.
As shown in in Frederic Hamidi's, the Base class' method can be exposed by the Derived class (under a different name), but that's not really invoking the Base's method, it is invoking a method of the Derived class which happens to call the Base's method.
Although this approach of having the Derived class supply a "proxy" to the method of the Base class, ultimately does what you ask for, it is probably a bad idea to do this: there's likely a flaw in the design of your object model: it would be a rather odd use case...
Base b = (Base)d;
Console.WriteLine(b.GetType()); //output:Derived
1)Casting cannot change it's class type.
class Derived : Base
{
public override void Foo() { Console.WriteLine("Derived"); }
public Base getBase()
{
return base; //compiler invalid
}
}
2) Above are invalid, because you never created any Base object instance when you created Derived object instance.
You created instance object of Derived class which inherited from Base class.
Hope, that explains why you could not invoke base function with derived object
Maybe Kii was looking for something like this
class Base
{
public virtual void Foo()
{
Console.WriteLine("Base");
}
}
class Derived : Base
{
// Change virtual with new
// public override void Foo() { Console.WriteLine("Derived"); }
public new void Foo()
{
Console.WriteLine("Derived");
}
}
static void Main(string[] args)
{
Derived d = new Derived();
d.Foo();// Output: Derived
typeof(Base).GetMethod("Foo").Invoke(d, null);// Output: Base
// Or you can cast
((Base)d).Foo();// Output: base
Console.ReadLine();
}
Related
I am new in c#.confuse with this question.
I Have override ToString() with override and new keyword.both are give me same output.then what is the difference between both.
here is my Example
class A
{
public new string ToString()
{
return "With New Keyword";
}
}
class B
{
public override string ToString()
{
return "With Override Keyword";
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
Console.WriteLine(a.ToString());
Console.WriteLine(b.ToString());
Console.Read();
}
}
Output
With New Keyword
With Override Keyword
I know its a silly question.
please anyone help me to give me difference between both methods.
I am not asking about difference between new and override key word.I want to know that difference between both method.In concept of Override Object methods.
It makes a difference when you do this:
object a = new A(); // notice the type of the variable here!
object b = new B();
Console.WriteLine(a.ToString());
Console.WriteLine(b.ToString());
a.ToString() will not call your implementation of ToString and will instead call object.ToString, which returns the fully qualified type name of the object. b.ToString() will call your implementation.
What you did in B is called overriding. What you did in A is called hiding. Hiding loses its effect when the compile time type of a variable is not that type anymore. Your implementation of ToString will only be called when the compile time type is A.
Learn more here.
You can easily google this.
From MSDN
In C#, a method in a derived class can have the same name as a method
in the base class. You can specify how the methods interact by using
the new and override keywords. The override modifier extends the base
class method, and the new modifier hides it. The difference is
illustrated in the examples in this topic.
In a console application, declare the following two classes, BaseClass
and DerivedClass. DerivedClass inherits from BaseClass.
In class B you are overriding ToString() method that is Object.ToString() because you have not inherited A. Now consider below example,
class A
{
public string ReturnString()
{
return "ClassA::Method";
}
}
class B : A
{
public newstring ReturnString()
{
return "ClassB::Method";
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
Console.WriteLine(a.ToString());
Console.WriteLine(b.ToString());
Console.Read();
}
}
Here you are hiding the method in class B as you have inherited Class A. So you will get the output as ClassA::Method for both method calls.
Now consider below example
class A
{
public virtual string ReturnString()
{
return "ClassA::Method";
}
}
class B : A
{
public override string ReturnString()
{
return "ClassB::Method";
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
Console.WriteLine(a.ToString());
Console.WriteLine(b.ToString());
Console.Read();
}
}
Here we have overridden the Class A's method in Class B. This means ClassB method is like extension or you can say it has different meaning than ClassA. You will get output like below
ClassA::Method
ClassB::Method
Let's suppose there is a following class:
public class foo{
internal virtual object M1(/*args*/){return null;}
internal virtual object[] M2(/*args*/){return null;}
public SomeStruct SomeMethod(){
return new SomeStruct
{
Obj = M1();
ObjArr = M2();
}
}
}
Using the following struct:
public class SomeStruct
{
public object Obj;
public object[] ObjArr;
}
Is there a way to make sure (preferably at compilation) to force either at least one method or exactly one method of class foo to be overriden?
Before anybody says it - I know it's possible to use one method and check if the result is array (or IEnumerable) and then assign it to the right field, but that takes more time then just running empty methods. I'm just wondering if it's possible to do it that way.
You could mark the methods abstract, and then you will be forced to implement both of the methods. This seems to be the most straightforward solution:
internal abstract object M1(/*args*/){return null;}
internal abstract object[] M2(/*args*/){return null;}
Another option, actually too complicated for this purpose, is to write a Roslyn code analyzer which will check the code and determines if it is valid.
As a side note: your fields should reside in the base class too. You could use generics if you want to make the types of them generic.
"No", basically. At least, not without writing your own custom code analyzer (perhaps via Roslyn), and considering what happens if X : foo overrides M1, and Y : X overrides M2.
You need to create a new method in your child class that hides the implementation of the base class, with the new return type. You cannot use virtual methods to overload a method like you're doing.Overloading of methods is done by changing the parameters, not the return type.
So either hide the parent method, in the child class, or create a method with another name.
Here is something that I can think of, just an example.
Run it here .Net Fiddle
using System;
public class a
{
public virtual object s(int a)
{
return a + 1;
}
}
public class b : a
{
public virtual object[] s(int a)
{
var arr = new object[]{a + 2};
return arr;
}
}
public class c : b
{
private a A = new a();
private b B = new b();
public c()
{
print(2);
}
public void print(int a)
{
var result = A.s(1);
Console.WriteLine("result : " + result);
var resultB = B.s(1);
//or resultB = base.s(1);
foreach (var r in resultB)
{
Console.WriteLine("result B : " + r);
}
}
}
public class Program
{
public static void Main()
{
c C = new c();
}
}
Consider these variants:
class A
{
public virtual void Doit()
{
}
}
class B : A
{
public new virtual void Doit()
{
}
}
or
class B : A
{
public override virtual void Doit()
{
}
}
I cannot find the difference in the returned results of the call typeof(B).GetMethod("Doit");
In both cases MethodInfo.DecalringType is class B and other properties seem the same.
Do I miss something or there is no way to distinguish them?
Update:
When I ran the sample in LINQPAd I noticed slight difference in Attributes property:
for new virtual value was - PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask
for override - PrivateScope, Public, Virtual, HideBySig
Update 2:
I googled about VtableLayoutMask and came back to StackOverflow
Udate 3:
resulting code:
public static class MethodInfoExtensions
{
public static bool IsOverriden(this MethodInfo method)
{
Contract.Requires<ArgumentNullException>(method != null, "method");
return method.IsVirtual
&& !method.IsStatic
// overriden exactly in this class
&& method.ReflectedType == method.DeclaringType
// not new and not declared for the first time in the class
&& method.GetBaseDefinition() != method;
}
}
Update: The documentation seems to imply that IsHideBySig is the answer, but it does not appear to be the case in practice.
Another strategy is to rely on the presence of the NewSlot attribute:
public static bool HasNewModifier(this MethodInfo method)
{
return (method.Attributes & MethodAttributes.VtableLayoutMask)
== MethodAttributes.NewSlot;
}
Original, incorrect answer follows.
You can rely on the IsHideBySig property. It will be true if the method has the new modifier.
Note the above only applies to C# methods. The documentation elaborates with:
When a member in a derived class is declared with the C# new modifier
or the Visual Basic Shadows modifier, it can hide a member of the same
name in the base class. C# hides base class members by signature. That
is, if the base class member has multiple overloads, the only one that
is hidden is the one that has the identical signature. By contrast,
Visual Basic hides all the base class overloads. Thus, IsHideBySig
returns false on a member declared with the Visual Basic Shadows
modifier, and true on a member declared with the C# new modifier.
The DeclaringType will be different if it was hidden with new. For example, run:
public class A
{
public virtual void WillBeInheritted()
{
}
public virtual void WillBeOverridden()
{
}
public virtual void WillBeHidden()
{
}
}
public class B : A
{
public override void WillBeOverridden()
{
}
public virtual new void WillBeHidden()
{
}
}
class Program
{
public static void Main(string[] args)
{
foreach(var meth in typeof(B).GetMethods())
{
Console.Write(meth.Name);
Console.Write(": ");
Console.Write(meth.GetBaseDefinition().DeclaringType.Name);
Console.Write(" ");
Console.WriteLine(meth.DeclaringType.Name);
}
Console.Read();
}
}
The output will be:
WillBeOverridden: A B
WillBeHidden: B B
WillBeInheritted: A A
WillBeHidden: A A
ToString: Object Object
Equals: Object Object
GetHashCode: Object Object
GetType: Object Object
WillBeInheritted has A as the declaring type for both the method and the base definition's declaring type.
WillBeOverridden has A for the base definition's declaring type, B for the declaring type.
WillBeHidden has two versions, the hidden one in A and the hiding one in B. This makes sense when we consider:
B b = new B();
A a = b;
b.WillBeHidden(); // calls hiding method.
a.WillBeHidden(); // calls hidden method on same object.
You can use GetBaseDefinition to find out where this method was first declared.
For example if you let var mi = typeof(B).GetMethod("Doit"); you can check if mi.GetBaseDefinition() == mi or if mi.GetBaseDefinition().DeclaringType == typeof(B) etc.
Here is an example:
class Animal : object
{
public virtual void M()
{
}
}
class Mammal : Animal
{
public override void M()
{
}
}
class Giraffe : Mammal
{
}
static class Test
{
internal static void Run()
{
var mi = typeof(Giraffe).GetMethod("M");
Console.WriteLine(mi.ReflectedType); // Giraffe
Console.WriteLine(mi.DeclaringType); // Mammal
Console.WriteLine(mi.GetBaseDefinition().DeclaringType); // Animal
}
}
The MethodInfo instance mi represents the override as inherited (unchanged) to Giraffe. And mi.GetBaseDefinition() fetches another MethodInfo which represents instead the method Animal.M which does not carry the override keyword in the C# source.
With the code below.
class Program
{
static void Main(string[] args)
{
BaseClass obj = new BaseClass();
DerivedClass obj2 = new DerivedClass();
var x = obj.Method(2);
var z = obj2.Method(1);
}
}
class BaseClass
{
public int Method(int i) { return i; }
}
class DerivedClass : BaseClass
{
public string Method(int i) { return i.ToString(); }
}
Why is that when I have the method in the derived class, the derived class object is calling its own function and if I do not have it, the derived class object is calling the base function?
If you want to override this behavior then you can mark a method with the new modifier which will explicitly hide a member in the class you derive from.
public new string Method(int i) { return i.ToString(); }
You should have received a warning from the compiler about this. Your new Method() method is implicitly hiding the base's (you can make this explicit using the new keyword, which will also silence the compiler warning). See also http://msdn.microsoft.com/en-us/library/aa691135%28v=vs.71%29.aspx.
Note that in C# there is no such thing as overloading a method based only on its output type. Just because your new method happens to return a string doesn't make its signature any different from the base's.
Note the following caveat about the dangers of hiding, which may also help to illustrate what is going on:
static void Main(string[] args)
{
BaseClass obj = new BaseClass();
DerivedClass obj2 = new DerivedClass();
var x = obj.Method(2); //returns 2
var z = obj2.Method(1); //returns 2 (2*2)
var a = ((BaseClass)obj2).Method(1); //returns 1 (base's implementation!)
}
class BaseClass
{
public int Method(int i) { return i; }
}
class DerivedClass : BaseClass
{
public int Method(int i) { return i * 2; }
}
This is unlike the behavior in the following code, which adds a new Method(string) overload:
static void Main(string[] args)
{
BaseClass obj = new BaseClass();
DerivedClass obj2 = new DerivedClass();
var x = obj.Method(2); //returns 2
var z = obj2.Method("1"); //returns "1"
var a = ((BaseClass)obj2).Method("1"); //returns "1"
}
class BaseClass
{
public int Method(int i) { return i; }
}
class DerivedClass : BaseClass
{
public string Method(string s) { return s; }
}
this is because , you hide the base method in derived class and when you create a object of derived class , it will call its own implementation. Compiler shouts when you do it without proper mechanism ( By using new keyword) and when you don't have the method in derived class then base class implementation kicked in.
Inheritance means that your DerivedClass automatically has all the members that BaseClass has. Therefore it also has the Method which returns int.
It's a bad idea to introduce a new method with the same name and the same arguments, in the DerivedClass. Because then DerivedClass has two methods with the same signature. That's why you get a warning from the compiler. Even if the warning goes away when you use the modifier of the new keyword, it's still a bad idea to have two methods with the same signature.
Instead, choose an unused name for the method in DerivedClass.
To answer your question more directly: When you have one method Method only, the one you wrote inside BaseClass, all is good. The DerivedClass inherits this method. This is why you can call it on obj2. But when you introduce a second method in DerivedClass, the call obj2.Method(1); needs to choose between two methods, because unfortunately there are two methods with the same signature. The rule in this case is to choose the method defined in DerivedClass. But note that it's the compile-time type that matters here. So if you said
BaseClass obj3 = new DerivedClass();
var w = obj3.Method(42);
even if the run-time type of obj3 is DerivedClass, it's the first method that gets called because of the compile-time type. Like I said, obj3 possesses both methods.
Given the following C# class definitions and code:
public class BaseClass
{
public virtual void MyMethod()
{
...do something...
}
}
public class A : BaseClass
{
public override void MyMethod()
{
...do something different...
}
}
public class B : BaseClass
{
public override void MyMethod()
{
...do something different...
}
}
public class AnotherObject
{
public AnotherObject(BaseClass someObject)
{
someObject.MyMethod(); //This calls the BaseClass method, unfortunately.
}
}
I would like to call the MyMethod() that is actually found in A or B, assuming the object passed in is actually an instance of A or B, not that which is found in BaseClass. Short of doing something like this:
public class AnotherObject
{
public AnotherObject(BaseClass someObject)
{
A temp1 = someObject as A;
if (A != null)
{
A.MyMethod();
}
B temp2 = someObject as B;
if (B != null)
{
B.MyMethod();
}
}
}
How can I do it?
Which method is called is determined via polymorphism on the type that is passed into the AnotherObject constructor:
AnotherObject a = new AnotherObject(new A()); // invokes A.MyMethod()
AnotherObject b = new AnotherObject(new B()); // invokes B.MyMethod()
AnotherObject c = new AnotherObject(new BaseClass()); //invokes BaseClass.MyMethod()
Sorry, but you are completely mistaken; this would go against the entire point of virtual methods. If someObject is an A then A.MyMethod will be invoked. If someObject is a B then B.MyMethod will be invoked. If someObject is a BaseClass and not an instance of a type derived from BaseClass then BaseClass.MyMethod will be invoked.
Let's use everyone's favorite example:
class Animal {
public virtual void Speak() {
Console.WriteLine("i can haz cheezburger?");
}
}
class Feeder {
public void Feed(Animal animal) { animal.Speak(); }
}
class Cat : Animal {
public override void Speak() { Console.WriteLine("Meow!"); }
}
class Dog : Animal {
public override void Speak() { Console.WriteLine("Woof!"); }
}
Then:
Animal a = new Animal();
Animal c = new Cat();
Animal d = new Dog();
Feeder f = new Feeder();
f.Feed(a);
f.Feed(c);
f.Feed(d);
This will print:
i can haz cheezburger?
Meow!
Woof!
Again, this is the entire point of virtual methods.
Further, we can go to the specification. From 10.6.3 (Virtual methods)
In a virtual method invocation, the run-time type of the instance for which that invocation takes place determines the actual method implementation to invoke.
(Bolding and italics in original.)
In precise terms, when a method named N is invoked with an argument list A on an instance with a compile-time type C and a run-time type R (where R is either C or a class derived from C), the invocation is processed as follows:
• First, overload resolution is applied to C, N, and A, to select a specific method M from the set of methods declared in and inherited by C. This is described in §7.5.5.1.
• Then, if M is a non-virtual method, M is invoked.
• Otherwise, M is a virtual method, and the most derived implementation of M with respect to R is invoked.
(Bolding not in original.)
Then, we need the definition of "most derived implementation of M." This is a nice recursive definition:
The most derived implementation of a virtual method M with respect to a class R is determined as follows:
• If R contains the introducing virtual declaration of M, then this is the most derived implementation of M.
• Otherwise, if R contains an override of M, then this is the most derived implementation of M.
• Otherwise, the most derived implementation of M with respect to R is the same as the most derived implementation of M with respect to the direct base class of R.
Thus, in our example above with Cat : Animal and Dog : Animal, when the parameter a to Feeder.Feed(Animal) is an instance of Cat then Cat.Speak is the most derived implementation. This is why we will see "Meow!" and not "i can haz cheezburger?"
If MyMethod() is abstract on the base class, then the version in the derived classes will be used. So if you don't need to call the instance in the base class, this would be an option.
static void Main(string[] args)
{
A classA = new A();
B classB = new B();
DoFunctionInClass(classA);
DoFunctionInClass(classB);
DoFunctionInClass(classA as BaseClass);
Console.ReadKey();
}
public static void DoFunctionInClass(BaseClass c)
{
c.MyMethod();
}
public abstract class BaseClass
{
public abstract void MyMethod();
}
public class A : BaseClass
{
public override void MyMethod()
{
Console.WriteLine("Class A");
}
}
public class B : BaseClass
{
public override void MyMethod()
{
Console.WriteLine("Class B");
}
}
If someObject passed in is class A, then A.MyMethod is called, not the base class implementation. Also look at the is keyword.
Because you've typed it as a BaseClass instead of an A or a B, the baseclass is the begin point for the method calls.
You might try using a generic:
public class AnotherObject
{
public AnotherObject<T>(T someObject) where T : BaseClass
{
someObject.MyMethod(); //This calls the BaseClass method, unfortunately.
}
}
I'm not sure how well this will fly in the constructor, but you might be able to move this to a different method.