I was working on this example:
Food classes:
public class Food { }
public class Meat : Food { }
public class Grass : Food { }
Animal
Unfortunately this is how the generic type system works in C#.
You have this problem because:
Animal
class has the Feed(T food)
method. This is key.Farm
class has a T
FoodSupply in order to feed the Animal
s within it.Farm
class needs to call Feed(T food)
on the Animal
but it can't do that without knowing what T
is.You can get around this with interfaces. Say you had an IAnimal
interface:
public interface IAnimal
{
void Feed(Food food);
}
then Animal
could implement it:
public abstract class Animal : IAnimal where TFood : Food
{
public void Feed(TFood food)
{
// we either need to check for null here
}
public void Feed(Food food)
{
// or we need to check food is TFood here
Feed(food as TFood);
}
}
Then you can change your Farm
class to get rid of the generics altogether:
public abstract class Farm where TAnimal : IAnimal
{
public List Animals;
public Food FoodSupply;
public void FeedAnimals()
{
foreach ( var animal in Animals )
{
animal.Feed(FoodSupply);
}
}
}
The problem now is that you can have a DairyFarm
(say) for which the FoodSupply
is Meat
- only you can't feed a Meat
to a Cow
as they only eat Grass
.
You need to have both type arguments to make use of generics - the compiler can't infer the specific type of Food
from the Animal
.