gpt4 book ai didi

java - Java 通配符泛型 的 .NET 等效项具有协方差和逆方差?

转载 作者:搜寻专家 更新时间:2023-11-01 02:12:49 25 4
gpt4 key购买 nike

我一直在尝试将一些使用(有界)通配符泛型的 Java 代码转换为 C#。我的问题是,Java 似乎允许泛型在与通配符一起使用时既是协变的又是逆变的。例如:

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);
}
}

...有效。

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 的泛型参数没有标记为协方差。

如果我改变这个:

interface IGeneric1<T> where T:Impl {

为此

interface IGeneric1<out T> where T:Impl 

错误消失了,但出现了另一个错误,对于在同一接口(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>'.

建议?

[另见 follow-up question对于更困难的场景]

最佳答案

您需要将 Java 通配符泛型方法转换为本身就是泛型的 C# 方法。例如,这个:

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<T> 指定作为 U 的类型约束.

这是因为在 Java 版本中,method1 的参数的类型实参有隐式约束。和 method2 : 如果参数必须是某种 IGeneric1<X>然后 X显然必须是 Impl因为否则它不可能实现 IGeneric1对于那种类型。

在 C# 中,约束必须是显式的,因此您需要重复 IGeneric1<T>IGeneric2<T>需要 T .

所以等效的代码是:

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;
}

关于java - Java 通配符泛型 <?> 的 .NET 等效项具有协方差和逆方差?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14277441/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com