C#: Overriding return types
c#, covariance, inheritance, overriding, types
Solution
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:
- Paolo Tedesco's first solution: Cat and Dog do not have a common base class.
- Paolo Tedesco's second solution: It is a bit complicated and hard to read.
- Daniel Daranas's solution: This works but it would clutter up your code with a lot of unnecessary casting and Debug.Assert() statements.
- hjb417's solutions: This solution doesn't let you keep your logic in a base class. The logic is pretty trivial in this example (calling a constructor) but in a real world example it wouldn't be.
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
- Explicit Interface Implementation
- new Modifier. I didn't use it in this simplified solution but you may need it in a more complicated solution. For example if you wanted to create an interface for BaseAnimal then you would need to use it in your decleration of "PooType Excrement".
- out Generic Modifier (Covariance). Again I didn't use it in this solution but if you wanted to do something like return `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.
Problem
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?