无法转换通用对象

时间:2013-10-31 15:09:21

标签: c#

以下内容不在fm.AddFoo(new StringFoo())上编译;错误消息:

参数1:无法从“ClassLibrary2.StringFoo”转换为“ClassLibrary2.IFoo”

这对我来说似乎合乎逻辑,因为字符串继承自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
    }
}

由于

2 个答案:

答案 0 :(得分:1)

虽然看起来IFoo是IFoo的子类,但事实并非如此。当你关闭IFoo&lt;&gt;时到特定类型是不是从IFoo创建IFoo的子类,它们是单独的,不同的类型,没有共同的层次结构。

答案 1 :(得分:1)

如果你可以使你的IFoo<>界面 协变 ,那就可以了,也就是说,如果你被允许将其声明更改为:

public interface IFoo<out T>

(注意out)。由于协方差,任何IFoo<string>也都是IFoo<object>,因为string是引用类型,并且派生自object

但是: IFoo<>方法的Handle成员以逆向方式使用type参数。因此,您的界面不能被声明为协变(out)。 (它可以被声明为逆变(in),但是对于上面的例子,它的方向是错误的。)

阅读仿制药中的协方差和逆变。

这里的根本问题是你的StringFoo只处理字符串。因此,它永远不能用作IFoo<object>,因为您可以传递Giraffe实例(Giraffe派生自object,因此Giraffeobject进入StringFoo,当Handlestring时,这是不可能的。