Reputation:
Consider this code:
public class Person
{
public virtual void UpdateLastLogin()
{
// business of last login here
}
}
public class Student : Person
{
public override void UpdateLastLogin()
{
// logging something specific to person
((Person)this).UpdatelastLogin();
}
}
Why Above code throws STACKOVERFLOW exception?
But this doesn't:
public class Person
{
public virtual void UpdateLastLogin()
{
// business of last login here
}
}
public class Student : Person
{
public override void UpdateLastLogin()
{
// logging something specific to person
base.UpdatelastLogin();
}
}
Upvotes: 11
Views: 2449
Reputation: 35842
It's because base keyword disables virtual method invocation, but casting doesn't.
Let's break it down:
With virtual
s and override
s, C# has an algorithm to find the correct method to call. This algorithm is called virtual method invocation.
When C# compiler is to invoke a method that has override
modifier, it tries to find the most overriden method. That is, it goes down the inheritance hierarchy of the run-time type to find the most overriden method. In this case, when you cast the Student
to its base class Person
, in run-time, what you really have is a derived class from Person
. Thus C# compiler tries to find the most overriden method, that is, a method that exists in the Student
class, and it calls that method. But that method again tries to cast Student
to Person
and again the chain goes on and on. Thus you see StackOverflowException
.
However, when you use base
to call the overridden base method, then compiler treats with that method (Person.UpdateLastLogin
) as a non-virtual method and won't apply virtual method invocation and resolution to it.
C# specification has a pretty reasonable explanation on override
and virtual
. I encourage you to read its 17.5.3 Virtual methods and 17.5.4 Override methods sections. Specifically quoted from specification:
A base-access disables the virtual invocation mechanism and simply treats the base method as a non-virtual method.
Upvotes: 17
Reputation: 137448
If you mean to call the base class implementation, use the base
keyword:
base.UpdatelastLogin();
Casting the reference to the base class really does nothing. That's the beauty of object-oriented programming! You don't need to know what type something is - you simply call a method on an object, and it's up the the implementation of that object how to behave.
Once you instantiate the child class, the entry in that object's vtable for UpdateLastLogin()
is always going to point to the child class, no matter the type of the reference.
Upvotes: 4