abstract class Animal { public virtual void Move() { } } class Dog : Animal { private string name; public Dog() { name = "Dog"; Move(); } public override void Move() { Console.WriteLine("{0} is running.", name); } }This piece of code just looks fine, nothing wrong with it. If you new an instance of the class Dog, it just print out "Dog is running.", as expected.
But it has a potential issue. If you have another class like this.
class Dingo : Dog { private string name; public Dingo() { name = "Dingo"; Move(); } public override void Move() { Console.WriteLine("{0} is tracking.", name); } }It just looks like the same as class Dog except that it derives from Dog. But if you new an instance of Dingo, "strange" thing happens. It prints out two lines, the first one is " is tracking", the second is "Dingo is tracking.", which is not expected.
The reason is that CLR initializes classes from the most derived one to the most basic one, then calls the constructors from the most basic one to the most derived one. But when it is calling the basic one's constructor, such as Dog(), inside the constructor it calls the virtual method Move(), which in this example actually is the Move method in Dingo class. And at that time the name of Dingo is not assigned yet, until it calls the Dingo's constructor.
So it is not safe to call virtual members in constructor, unless it is the most derived type, in which case you can use the key work "sealed" to prevent others inheriting from this type.
No comments:
Post a Comment