问题描述
||
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
比than5ѭ派生更多,因此会产生编译器错误。
这个例子是人为设计的,但是我们要处理的实现是从工厂返回MyFoo
的实现。
尽管将ѭ3as用作参数,但是当尝试将其分配给通用接口时它也是输出,但是在这里我无法使用out
关键字。我们如何解决这个问题?
解决方法
您的IFoo接口在这种用法中似乎是错误的,应该是:
public interface IFoo<out T,**out** U>
U
被淘汰。请记住,“ 8”泛型类型参数意味着它可以变化“向外”。也就是说,可以将类型隐式扩展为更大的类型。但是,“ 12”表示您可以隐式地将“向内”类型缩小为更具体的类型。当然,这些只是粗略的类比。
因此,在分配hmm
的情况下,您隐式地尝试将U
的接口泛型参数从Derived
扩展到Base
,但是接口声明它正在变窄(in
):
IFoo<IShape,Base> hmm = new MyFoo();
因此它无法进行隐式转换。如果您确实希望能够隐式扩展此接口,则第二个类型参数应为out
而不是in
。
更新:发表您的评论后,我发现最大的难题是您希望它同时输入和输出,这实际上是不可能的。由于这是一个反输入,因此您不能将接口协变地分配给IFoo<IShape,Base>
,很不幸。
您可能需要围绕无法分配给IFoo<IShape,Base>
的事实进行编码,或者可以通过以下方式创建Foo:
public class MyFoo : IFoo<Rectangle,Base>
然后在实现中强制转换为Rectangle
。最主要的是,同一类型参数不能同时具有协方差和协方差。
这有意义吗?
,可以将Base转换为Rectangle的东西也会将Derived转换为IShape。但是,某些可以将“派生”转换为“矩形”的事物可能无法对Base执行任何有用的操作。您正确地确定了第二个参数的协方差说明符需要为“ in”,但是随后尝试以与实际支持相反的方式使用协方差。