.NET相当于Java的泛型通配符<>与合作和禁忌变异? [英] .NET equivalent for Java wildcard generics <?> with co- and contra- variance?

查看:190
本文介绍了.NET相当于Java的泛型通配符<>与合作和禁忌变异?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我卡试图转换使用(界)通配符泛型C#一些Java code。 我的问题是,爪哇似乎允许具有通配符当用于一般类型是既协变和逆变。例如:

I'm stuck trying to translate some Java code that uses (bounded) wildcard generics to C#. My problem is, Java seems to allow a generic type to be both covariant and contravariant when used with a wildcard. For instance:

Java的:

interface IInterf { }

class Impl implements IInterf { }

interface IGeneric1<T extends Impl> {
    void method1(IGeneric2<?> val);
    void method1WithParam(T val);
}

interface IGeneric2<T extends Impl> {
    void method2(IGeneric1<?> val);
}

abstract class Generic<T extends Impl> implements IGeneric1<T>, IGeneric2<T> {
    public void method1(IGeneric2<?> val2) {
        val2.method2(this);
    }
}

...作品。

...works.

C#相当于(?)

interface IInterf { }

class Impl : IInterf { }

interface IGeneric1<T> where T:Impl {
  //Java was: 
  //void method1(IGeneric2<?> val2);
    void method1(IGeneric2<Impl> val);
    void method1WithParam(T to);
}

interface IGeneric2<T>where T:Impl {
    void method2(IGeneric1<Impl> val);
}

abstract class Generic<T> : IGeneric1<T>, IGeneric2<T> where T : Impl
{
  //Java was: 
  //public void method1(IGeneric2<?> val2) {
    public void method1(IGeneric2<Impl> val2)
    {
         val2.method2(this); //'this': Argument type 'Generic<T>' is not 
                             //assignable to parameter type 'IGeneric1<Impl>'
    }

    public abstract void method1WithParam(T to);
    public abstract void method2(IGeneric1<Impl> val);
}

...编译失败 - 见注释错误。这是可以预料的,因为IGeneric的泛型参数未标记出的协方差。

...fails to compile - see the error in the comment. Which is to be expected, since IGeneric's generic parameter is not marked 'out' for covariance.

如果我改变这样的:

interface IGeneric1<T> where T:Impl {

interface IGeneric1<out T> where T:Impl 

错误消失,但是另外一个的出现,为的方法是采用相同的接口,在泛型参数声明:

the error goes away, but another one appears, for the declaration of the method that takes a generic parameter inside the same interface:

interface IGeneric1<T> where T:Impl {
    void method1WithParam(T val);  //Parameter must be input-safe. 
                      //Invalid variance: The type parameter 'T' must be
                      //contravariantly valid on 'IGeneric1<out T>'.

建议?

[另请参见后续问题一个有点困难的情况]

[Also see the follow-up question for a somewhat harder scenario]

推荐答案

您需要翻译的Java通配符的通用方法,以C#中的方法是通用在自己的权利。例如,这

You need to translate the Java wildcard generic methods to C# methods that are generic in their own right. For example, this:

interface IGeneric2<T extends Impl> {
    void method2(IGeneric1<?> val);
}

应转换为

interface IGeneric2<T>where T:Impl {
    void method2<U>(IGeneric1<U> val) where U:Impl;
}

这是需要重复的类型约束 T 通过指定 IGeneric1&LT; T&GT; 作为类型约束 U

It is necessary to repeat the type constraint for T specified by IGeneric1<T> as the type constraint for U.

这样做的原因是,在Java版本还有的的约束方法1的参数的类型参数方法2 :如果该参数必须是某种 IGeneric1与其中的X - GT; 然后 X 显然必须是默认地将Impl ,因为否则就不可能实现 IGeneric1 该类型。

The reason for this is that in the Java version there are implicit constraints for the type arguments of the parameters of method1 and method2: if the parameter must be some kind of IGeneric1<X> then X must obviously be an Impl because otherwise it could not possibly implement IGeneric1 for that type.

在C#中的约束必须是明确的,所以你重复 IGeneric1&LT; T&GT; IGeneric2&LT; T&GT; 需要 T 的。

In C# the constraints must be explicit, so you repeat what IGeneric1<T> and IGeneric2<T> require of T.

因此​​,相当于code将是:

So the equivalent code would be:

interface IInterf { }

class Impl : IInterf { }

interface IGeneric1<T> where T:Impl {
    void method1<U>(IGeneric2<U> val) where U:Impl;
    void method1WithParam(T to);
}

interface IGeneric2<T>where T:Impl {
    void method2<U>(IGeneric1<U> val) where U:Impl;
}

abstract class Generic<T> : IGeneric1<T>, IGeneric2<T> where T : Impl
{
    public void method1<U>(IGeneric2<U> val2) where U:Impl
    {
        val2.method2(this);
    }

    public abstract void method1WithParam(T to);
    public abstract void method2<U>(IGeneric1<U> val) where U:Impl;
}

这篇关于.NET相当于Java的泛型通配符&LT;&GT;与合作和禁忌变异?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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