public interface IShape{}
public class Rectangle : IShape{}
public class Base{}
public class Derived : Base{}
public interface IFoo<out T, in U>
where T : IShape
where U : Base
{
T Convert(U myType);
}
public class MyFoo : IFoo<Rectangle, Derived>
{
public Rectangle Convert(Derived myType)
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string[] args)
{
IFoo<IShape, Base> hmm = new MyFoo();
}
}
鉴于上面的代码,编译器无法确定如何将类型MyFoo
分配给IFoo<IShape, Base>
,大概是因为U
被设置为out意味着它可以接受更少的派生。但是,Derived
比Base
派生的更多,因此会生成编译器错误。
这个例子是设计的,但我们正在处理的实现是从工厂返回MyFoo
的实现。
虽然U
用作参数,但在尝试将其分配给通用界面时它也是输出,但我在此处无法使用out
关键字。我们怎么能解决这个问题?
答案 0 :(得分:1)
您的IFoo界面在此用法中似乎有误,应该是:
public interface IFoo<out T, **out** U>
U
出局。请记住,out
泛型类型参数意味着它可以“向外”变化。也就是说,您可以隐式地将类型扩展为更宽的类型。但是,In
意味着您可以隐式地将“内部”类型缩小为更具体的类型。当然,这些只是粗略的比喻。
因此,在分配hmm
的情况下,您隐含地尝试将U
的接口泛型类型参数从Derived
扩展到Base
,但是interface声明它变窄(in
):
IFoo<IShape, Base> hmm = new MyFoo();
所以它无法进行隐式转换。如果您真的希望能够隐式扩展此接口,则第二个类型参数应为out
而不是in
。
更新:在您发表评论之后,我发现最大的难题是您希望它既可以进出又出现,这实际上是不可能的因为它是一个逆变输入,所以您不能将该接口共同分配给{{不幸的是,1}}。
您需要围绕无法分配给IFoo<IShape, Base>
的事实进行编码,或者您可以做的是创建Foo:
IFoo<IShape,Base>
然后在实现中转换为public class MyFoo : IFoo<Rectangle, Base>
。主要的是你不能在同一类型参数上同时具有协方差和逆变。
这有意义吗?
答案 1 :(得分:0)
可以将Base转换为Rectangle的东西也会将Derived转换为IShape。但是,可以将Derived转换为Rectangle的东西可能无法对Base执行任何有用的操作。您正确地确定了第二个参数的协方差说明符需要“在”中,然后尝试以与实际支持相反的方式使用协方差。