Eric Scherrer
Eric Scherrer

Reputation: 3408

Cannot convert generic object

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

Answers (2)

Jeppe Stig Nielsen
Jeppe Stig Nielsen

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

Patrick
Patrick

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

Related Questions