I have three classes called Animal, Cat and Dog where Cat and Dog inherit from Animal:
public class Animal
{
public void Talk()
{
Console.WriteLine("Parent");
}
}
public class Cat : Animal
{
public new void Talk()
{
Console.WriteLine("Child(Cat)");
}
}
public class Dog : Animal
{
public new void Talk()
{
Console.WriteLine("Child(Dog)");
}
}
I have another method in another class that calls the Talk() method on an animal:
public static Animal FirstKindOfTalk(Animal animal)
{
if (animal.GetType() == typeof(Cat))
{
var changed = animal as Cat;
if (changed is not null)
changed.Talk();
return changed;
}
else if (animal.GetType() == typeof(Dog))
{
var changed = animal as Dog;
if (changed is not null)
changed.Talk();
return changed;
}
return animal;
}
FirstKindOfTalk(new Animal()); => Parent gets printed in the console.
FirstKindOfTalk(new Cat()); => Child(Cat) gets printed in the console.
FirstKindOfTalk(new Dog()); => Child(Dog) gets printed in the console.
I have to explicitly cast the parameter to their own type (Cat or Dog) due to Upcasting, in order to be able to run the specific implementation of those classes from the method Talk(). This is because I'm not using virtual and override in my code, if I used them, then the runtime would run the implementation of the passed in parameter from the method.
The Problem I prefer to write the method as the following:
public static Animal SecondKindOfTalk(Animal animal)
{
var changed = animal;
if (animal.GetType() == typeof(Cat))
{
changed = animal as Cat;
changed.Talk();
return changed;
}
else if (animal.GetType() == typeof(Dog))
{
changed = animal as Dog;
changed.Talk();
return changed;
}
return changed;
}
FirstKindOfTalk(new Animal()); => Parent gets printed in the console.
FirstKindOfTalk(new Cat()); => Parent gets printed in the console.
FirstKindOfTalk(new Dog()); => Parent gets printed in the console.
What is causing this behavior?
I know using virtual and override is the better way, but I have to work on an existing project where methods from the base class aren't defined as virtual, and I cannot change them either.
if (animal is Cat cat) { cat.Talk(); }and remove thereturninside theifas it's the same object anyway.newmodifier to hide (not replace, not override) already existing members with "new" members. Instead, either usevirtualandoverride. Or pick different names so no hiding occurs, and no confusion arises. In your case, call the methodpublic void Meow()onCat, and usepublic void Bark()onDog, and keeppublic void Talk()on the base class. Because this naming reflects the reality: You have three unrelated methods, and you can call them only on the instances where they exist. But this removes most of your confusion!.Talk, the binding occurs at compile-time, i.e. before you even start running the program, and based on the static compile-time type of the variable (or other expression) on which you use.Talk. This binding is final. It will not suddenly move to another member.Talkwhen the program runs and it turns out the run-time type of the object is more derived than the compile-time type.FirstKindOfTalk(new Animal());andSecondKindOfTalk(new Animal());won't print anything actually because it's neithertypeof(Cat)nortypeof(Dog).