gpt4 book ai didi

java - .NET 等效于 Java 有界通配符 (IInterf)?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:18:17 25 4
gpt4 key购买 nike

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

[这是之前 question 的衍生产品处理一个更简单的有界通配符案例]

Java - 有效:

class Impl { }

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

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

abstract class Generic2<T extends Impl> implements IGeneric2<T> {

// !! field using wildcard
protected IGeneric1<?> elem;

public void method2(IGeneric1<?> val1) {
val1.method1(this);

//assignment from wildcard to wildcard
elem = val1;
}
}

abstract class Generic<T extends Impl> implements IGeneric1<T>, IGeneric2<T> {

public void method1(IGeneric2<?> val2) {
val2.method2(this);
}
}

C# - 无法编译...

class Impl { }

interface IGeneric1<T> where T:Impl {
//in Java:
//void method1(IGeneric2<?> val);
void method1<U>(IGeneric2<U> val) where U : Impl; //see this Q for 'why'
// https://stackoverflow.com/a/14277742/11545

T method1WithParam(T to);
}

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

abstract class Generic2<T, TU>: IGeneric2<T> //added new type TU
where T : Impl
where TU : Impl
{
//in Java:
//protected IGeneric1<?> elem;
protected IGeneric1<TU> elem;

//in Java:
//public void method2(IGeneric1<?> val1)
public void method2<U>(IGeneric1<U> val)
where U : TU //using TU as constraint
{
elem = val; //Cannot convert source type 'IGeneric1<U>'
//to target type 'IGeneric1<TU>'
}
public abstract void method1WithParam(T to);
}

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

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

如果我改变 interface IGeneric1<T>interface IGeneric1<out T>上面的错误消失了,但是method1WithParam(T)提示差异:

Parameter must be input-safe. Invalid variance: The type parameter 'T' must be
contravariantly valid on 'IGeneric1<out T>'.

最佳答案

首先我要说的是,看起来设计评审肯定已经开始了。原始 Java 类聚合了一个 IGeneric1<?>成员,但不知道它的类型参数就不可能调用 method1WithParam以类型安全的方式在其上。

这意味着elem只能用于调用其 method1成员,其签名不依赖于 IGeneric1 的类型参数.由此得出 method1可以分解成一个非通用接口(interface):

// C# code:
interface INotGeneric1 {
void method1<T>(IGeneric2<T> val) where T : Impl;
}

interface IGeneric1<T> : INotGeneric1 where T : Impl {
T method1WithParam(T to);
}

在此之后,class Generic2可以聚合 INotGeneric1改为成员:

abstract class Generic2<T>: IGeneric2<T> where T : Impl
{
protected INotGeneric1 elem;

// It's highly likely that you would want to change the type of val
// to INotGeneric1 as well, there's no obvious reason to require an
// IGeneric1<U>
public void method2<U>(IGeneric1<U> val) where U : Impl
{
elem = val; // this is now OK
}
}

当然现在你不能调用elem.method1WithParam除非你求助于强制转换或反射,即使已知存在这样的方法并且它对某些未知类型是通用的 X作为类型参数。但是,这与 Java 代码具有相同的限制;只是 C# 编译器不会接受此代码,而 Java 只会在您尝试调用 method1WithParam1 时才会提示。 .

关于java - .NET 等效于 Java 有界通配符 (IInterf<?>)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14289518/

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