.NET相当于Java的泛型通配符&LT;&GT;与合作和禁忌变异? [英] .NET equivalent for Java wildcard generics <?> with co- and contra- variance?
问题描述
我卡试图转换使用(界)通配符泛型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屋!