使用通用接口约束时的协方差/逆差异难题 [英] Covariance/Contravariance Conundrum when using generic interface constraints

查看:148
本文介绍了使用通用接口约束时的协方差/逆差异难题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

    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意味着它可以接受更少的派生。但是,派生 Base 派生的更多,因此会产生编译错误。

Given the above code, the compiler is unable to determine how to assign the type MyFoo to IFoo<IShape, Base>, presumably because U is set as an out meaning that it can accept less derived. However, Derived is, well, more derived than Base, so generates a compiler error.

这个例子是设计的,但我们正在处理的实现是从工厂返回 MyFoo 的实现。

This example is contrived but the implementation we are dealing with is one in which MyFoo would be returned from a factory.

虽然 U 用作参数,但在尝试将其分配给通用接口时它也是输出但我无法在此处使用 out 关键字。我们怎么能解决这个问题呢?

Although U is used as a parameter, it is also an output when trying to assign it to the generic interface but I am unable to use the out keyword here. How could we work around this?

推荐答案

你的IFoo界面在这个用法中似乎是错误的,它应该是:

Your IFoo interface seems to be wrong in this usage, it should be:

public interface IFoo<out T, **out** U>

U 退出。请记住, out 泛型类型参数意味着它可以向外变化。也就是说,您可以隐式地将类型扩展为更宽的类型。 但是,在中,意味着您可以隐式地将内部类型缩小为更具体的类型。当然,这些只是粗略的类比。

With U being out. Remember that an out generic type parameter means that it can vary "outwards". That is, you can widen the type implicitly to a wider type. In, though, means that you can implicitly narrow the type "inwards" to a more specific type. These are just rough analogies, of course.

因此,在分配 hmm 的情况下,你就是隐式尝试将 U 的接口泛型类型参数从派生扩展为 Base ,但界面宣称它正在缩小( in ):

So in the case of the assignment of hmm, you are are implicitly trying to widen the interface generic type parameter for U from Derived to Base, but the interface declares it to be narrowing (in):

IFoo<IShape, Base> hmm = new MyFoo();

因此无法进行隐式转换。如果你真的希望能够隐式地扩展这个接口,那么第二个类型的参数应该是 out 而不是中的

So it can't make the implicit conversion. If you really want to be able to widen this interface implicitly, the second type argument should be out instead of in.

更新:在您的评论之后,我发现最大的困境是您希望它既可以进出也可以进入,这是不可能的因为它是一个逆变输入,遗憾的是,你无法将界面协调地分配给 IFoo< IShape,Base>

Update: after your comments, I see that the big dilemma is that you want it to be both in and out, which isn't really possible Since it's a contravariant input, you can't assign the interface covariantly to IFoo<IShape, Base>, unfortunately.

您需要围绕无法分配到 IFoo< IShape,Base> 或者什么的事实进行编码你可以做的是创建Foo:

You either need to code around the fact you can't assign to IFoo<IShape,Base> or what you could do is create Foo as:

public class MyFoo:IFoo< Rectangle,Base>

然后在实现中转换为 Rectangle 。主要的是你不能在同一类型参数上同时具有协方差和逆变。

And then cast to Rectangle inside the implementation. The main thing is you can't have both covariance and contravariance on the same type parameter.

这有意义吗?

这篇关于使用通用接口约束时的协方差/逆差异难题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆