在 Kotlin 中,您可以使用泛型来实现:
class Foo<T> {
fun toto(arg: Bar<in T>) {}
fun tata(arg: Baz<out T>) {}
}
C# 中的等价物是什么?
我尝试像这样在 C# 中复制代码
class Foo<T> {
public void toto(Bar<in T> arg) {}
public void tata(Baz<out T> arg) {}
}
我预计它会起作用,但它说
Type argument is missing
。
C# 没有使用站点差异 - 它只有声明站点差异(Kotlin 也有),但仅限于接口类型。也就是说,您只能在接口的声明中指定类型参数的方差,例如
// this just so happens to also be valid Kotlin :)
interface IBar<in T> { ... }
// or
interface IBar<out T> { ... }
“模拟”使用站点差异的一种方法是将类划分为“可以协变使用的东西”(输出位置中的
T
)和“可以逆变使用的东西”(在输出位置中T
)输入位置)。为这两组中的每组声明一个接口,并具有正确的方差。
interface ICovariantBar<out T> {
T Output();
}
interface IContravariantBar<in T> {
void Input(T t);
}
class Bar<T>: ICovariantBar<T>, IContravariantBar<T> {
public void Input(T t) { ... }
public T Output() { ... }
}
然后您可以在 Kotlin 中使用
ICovariantBar<T>
代替 Bar<out T>
,在 Kotlin 中使用 IContravariantBar<T>
代替 Bar<in T>
。
这当然有一些注意事项。从我的头顶上看:
Bar<T>
T
是协变时,您仍然可以在输入位置使用带有 T
的方法,而当 T
是逆变时,您仍然可以在输出位置使用带有 T
的方法。只是类型 T
将分别替换为 Nothing
(“底部类型”)或 T
的边界。您需要添加一些额外的方法才能在 C# 中执行相同的操作