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 Animals 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.