Reputation: 3408
The following does not compile on line fm.AddFoo(new StringFoo()); with the error message:
Argument 1: cannot convert from 'ClassLibrary2.StringFoo' to 'ClassLibrary2.IFoo'
This seems logical to me since string inherits from object.
public interface IFoo<T>
{
void Handle(T value);
}
public class StringFoo : IFoo<string>
{
public void Handle(string value)
{ }
}
public class ObjectFoo : IFoo<object>
{
public void Handle(object value)
{ }
}
public class FooManager
{
private readonly List<IFoo<object>> _foos;
public FooManager()
{
_foos = new List<IFoo<object>>();
}
public void AddFoo(IFoo<object> foo)
{
_foos.Add(foo);
}
}
public class Bad
{
public Bad()
{
var fm = new FooManager();
fm.AddFoo(new StringFoo()); \\ This does not compile
}
}
Thanks
Upvotes: 1
Views: 311
Reputation: 62002
If you could make your IFoo<>
interface covariant it would work, that is if you were allowed to change the declaration of it into:
public interface IFoo<out T>
(note the out
). Because with covariance any IFoo<string>
would also be an IFoo<object>
because string
is a reference type and derives from object
.
But: A member of IFoo<>
, the Handle
method, uses the type parameter in a contravariant manner. So your interface cannot be declared covariant (out
). (It could be declared contravariant (in
) but that goes in the wrong direction for your example above.)
Read up on covariance and contravariance in generics.
The fundamental problem here is that your StringFoo
handles only strings. Therefore it can never be used as an IFoo<object>
because then you could pass for example a Giraffe
instance (Giraffe
derives from object
, so a Giraffe
is an object
) into the StringFoo
, and that is impossible when its Handle
takes a string
.
Upvotes: 1
Reputation: 68
Although it may seem like IFoo is a subclass of IFoo it is not. When you close IFoo<> to a specific type is is not creating a subclass of IFoo from IFoo, they are seperate and distinct types with no common hierarchy.
Upvotes: 1