Is there way to override return types in C#? If so how, and if not why and what is a recommended way of doing it?
My case is that I have an interface with an abstract base class and descendants of that. I would like to do this (ok not really, but as an example!) :
public interface Animal
{
Poo Excrement { get; }
}
public class AnimalBase
{
public virtual Poo Excrement { get { return new Poo(); } }
}
public class Dog
{
// No override, just return normal poo like normal animal
}
public class Cat
{
public override RadioactivePoo Excrement { get { return new RadioActivePoo(); } }
}
RadioactivePoo
of course inherits from Poo
.
My reason for wanting this is so that those who use Cat
objects could use the Excrement
property without having to cast the Poo
into RadioactivePoo
while for example the Cat
could still be part of an Animal
list where users may not necessarily be aware or care about their radioactive poo. Hope that made sense...
As far as I can see the compiler doesn't allow this at least. So I guess it is impossible. But what would you recommend as a solution to this?
I know there are a lot of solutions for this problem already but I think I've come up with one that fixes the issues I had with the existing solutions.
I wasn't happy with the some of the existing solutions for the following reasons:
My Solution
This solution should overcome all of the issues I mentioned above by using both generics and method hiding.
public class Poo { }
public class RadioactivePoo : Poo { }
interface IAnimal
{
Poo Excrement { get; }
}
public class BaseAnimal<PooType> : IAnimal
where PooType : Poo, new()
{
Poo IAnimal.Excrement { get { return (Poo)this.Excrement; } }
public PooType Excrement
{
get { return new PooType(); }
}
}
public class Dog : BaseAnimal<Poo> { }
public class Cat : BaseAnimal<RadioactivePoo> { }
With this solution you don't need to override anything in Dog OR Cat! Here is some sample usage:
Cat bruce = new Cat();
IAnimal bruceAsAnimal = bruce as IAnimal;
Console.WriteLine(bruce.Excrement.ToString());
Console.WriteLine(bruceAsAnimal.Excrement.ToString());
This will output: "RadioactivePoo" twice which shows that polymorphism has not been broken.
Further Reading
MyType<Poo>
from IAnimal and return MyType<PooType>
from BaseAnimal then you would need to use it to be able to cast between the two.