I ran into a interesting issue last week and I am not sure I truly understand the polymorphic nature of the following code. I created this sample based some code that I wrote.
Basic Setup
Here is the code
// Does not work as expected
// Calls the Trainer Train not the DogTrainer Train
var getTrainer = new Func<Trainer>(() => new DogTrainer(new Dog()));
var funcTrainer = getTrainer();
Console.WriteLine(funcTrainer.Train());
Now if I use a Interface as the return type it does work as expected "IF" I have the interface directly marked on the "DogTrainer" subclass
// Works as expected
var getITrainer = new Func<ITrainer>(() => new DogTrainer(new Dog()));
var funcITrainer = getITrainer();
Console.WriteLine(funcITrainer.Train());
If I do not have the interface on the subclass it does not work as expected. See Example
// Does not work as expected
// Calls the Trainer Train not the Dog Trainer Train
var getITrainerWithNoInterface = new Func<ITrainer>(() => new DogTrainerWithNoInterface(new Dog()));
var funcITrainerWithNoInterface = getITrainerWithNoInterface();
Console.WriteLine(funcITrainerWithNoInterface.Train());
If someone could let me know what I am missing here, this behavior is not what I expected. When I discovered this bug in my code I was able to solve it, what I am looking for here is the "Why" this is happening.
Here is DogTrainerWithNoInterface which is likely the main part of the puzzle (Trainer:ITrainer)
public class DogTrainerWithNoInterface : Trainer
{
public DogTrainerWithNoInterface(IAnimal animal)
: base(animal)
{ }
public new string Train()
{
return $"Speak Ubu, Speak : {Animal.Speak()}";
}
}
NOTE: This answer is purely for describing the "new" issue due to not fitting in the comment. Please ignore voting as it doesn't fully answer his question.
Sample from OP's link:
public class DogTrainer : Trainer, ITrainer
{
public DogTrainer(IAnimal animal)
: base(animal)
{ }
public new string Train()
{
return $"Speak Ubu, Speak : {Animal.Speak()}";
}
}
Do not use new when declaring methods/properties. Make them virtual on the base and then override them. What you are doing is hiding the method on your base.
You can only get your new method to invoke when working with that specific type (DogTrainer). Any down-casting to the base will invoke it's method i.e. working with a variable declared as Trainer or ITrainer.
Knowing When to Use Override and New Keywords (C# Programming Guide)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With