I have a good understanding of OOP in general, inheritance and polymorphism, interfaces, etc. I encountered a strange situation and I don’t understand why it does not work at all…
EDIT : Ok, I found out that covariance (or contravariance?) may solve this problem, but crucially
we’re still using .NET 2.0
How can I solve this without moving to C# 4.0 ?
Here is the situation. Given these two classes :
public class CustomCollectionType<T> : IEnumerable<T>
{
/* Implementation here, not really important */
}
public class Entity : EntityBase
{
/* Implentation here, not important */
}
The compiler complains when I try to have this generic method
public void LoopThrough(IEnumerable<EntityBase> entityList)
{
foreach(EntityBase entity in entityList)
{
DoSomething(entity);
}
}
And try to use it this way :
CustomCollectionType<Entity> entityList;
/* Add items to list */
LoopThrough(entityList);
Error says I cannot convert from CustomCollectionType<Entity> to IEnumerable<EntityBase>.
However, I can do this :
public void Foo(EntityBase entity)
{
entity.DoSomething();
}
Foo(new Entity());
And this :
public void Bar(IEnumerable<Entity> entityList)
{ ... }
CustomCollectionType<Entity> entityList;
Bar(entityList);
Why can’t I create my method with the highest classes in the hierarchy? The types are obviously compatible… Am I missing something ?
EDIT : I want to solve this problem without altering the existing classes in any way, so creating a new method in any of the classes, or implementing an additional interface is out of the question.
Let’s consider your first case. You have:
and you call
This fails in C# 3.0; it succeeds in C# 4.0 because
IEnumerable<T>is now covariant in T; a sequence of apples can be used as a sequence of fruits.To make it work in C# 3.0 you can use the
Castsequence operator.To make it work in C# 2.0, implement the Cast sequence operator yourself. It is only a couple lines of code.
Note that in C# 4.0 it will still not be legal to say:
because of course you can say:
and you just put an orange into a bowl that can only contain apples.