I’ve been busy with C# 4.0 generics, and now I basically want to do something like this:
public abstract class GenericTree<T> : Tree
where T : Fruit
{
public Tree(IFruitCollection<T> fruits)
: base(fruits) { }
}
The base Tree class looks like this:
public abstract class Tree
{
private IFruitCollection<Fruit> fruits;
public IFruitCollection<Fruit> GetFruits
{
get { return fruits; }
}
public Tree(IFruitCollection<Fruit> fruits)
{
this.fruits = fruits;
}
}
Here is my first problem. The constructor of GenericTree can’t cast the the generic collection to a fruit collection. I’ve also got an implementation of the GenericTree:
public class AppleTree : GenericTree<Apple>
{
public AppleTree()
: base(new FruitCollection<Apple>) { }
}
Here’s my second problem. When I add fruit to an instance of AppleTree, using myAppleTree.GetFruits.Add(…), I am not restricted to apples only. I am allowed to add all kinds of fruit. I don’t want this.
I tried to solve that problem by adding this to the GenericTree:
new public IFruitCollection<T> GetFruits
{
get { return base.GetFruits as IFruitCollection<T>; }
}
But this is not possible either. It somehow always returns null. It could be possible that this will be solved, when my first problem is solved.
The IFruitCollection interface looks like this:
public interface IFruitCollection<T> : ICollection<T>
where T : Fruit { ... }
And the FruitCollection class is a simple implementation of the Collection class.
Oh, and of course, the Apple class extends the Fruit class.
The solution is to make the IFruitCollection interface compatible with both covariance and contravariance. But how do I achieve this? The “in” or “out” parameter keywords are not possible, because the ICollection interface doesn’t allow it.
Thanks a lot for your help!
I think I found my solution, while I was trying out phoog’s workaround. Thanks, phoog!
At first I didn’t give GenericTree his own FruitCollection. Mosty because the base class often loops through his own collection, for example to update the fruits. This resulted into fruits not updating, because they were added to the GenericTree’s collection, not to the base collection.
But eventually I realised that casting those collections is never going to work either.
Now I’ve made another FruitCollection class that automatically adds and removes components to the base FruitCollection, and vice versa. This solution works great for me!
This helped me: How to handle add to list event?