我一直试图将一些使用(有界)通配符泛型的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的泛型参数未标记为“ out”用于协方差。
如果我更改此:
interface IGeneric1<T> where T:Impl {
对此
interface IGeneric1<out T> where T:Impl
错误消失了,但出现了另一个错误,因为该方法的声明在同一接口内采用了通用参数:
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>'.
有什么建议吗?
[另请参阅后续问题,了解更困难的情况
您需要将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版本中,and 参数的类型实参存在 隐式
约束:如果参数必须为某种,那么显然必须为an,因为否则它将无法实现该类型。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代码转换为C#。我的问题是,Java与通配符一起使用时似乎允许泛型既协变又协变。 [这是从先前的问题中衍生出来的,该问题处理的是更简单的有界通配符案例] Java-作品: C# -无法编译… 如果我更改interface IGeneric1 为interface IGeneric1 上述错误,错误会消失,但会method1WithPara
问题内容: 请显示一个有关Java中协方差和逆方差的好例子。 问题答案: 协方差: Sub#getSomething是协变的,因为它返回Super#getSomething的返回类型的子类(但完全填充了Super.getSomething()的协定) 逆差 Sub#doSomething是互变的,因为它采用了Super#doSomething的参数的超类的参数(但是,再次填充了Super#doSo
问题内容: 谁能解释我,编程语言理论中协变和逆变的概念吗? 问题答案: 协方差 非常简单,最好从某些收集类的角度来考虑。我们可以 参数化 的一些类型参数类。也就是说,我们的列表包含some 类型的元素。如果,列表将是协变的 S是Tiff列表的子类型List [S]是List [T]的子类型 (在这里,我使用数学定义 iff 表示 当且仅当 。) 也就是说,a 是一个 。如果有一些例程接受a 作为参
我正在阅读为什么Java中的数组协方差不好(为什么数组是协方差的,而泛型是不变的?)。如果是的子类型,则是的子类型。这是一个问题,因为这样的事情是可以做的: 这与“正确”实现的泛型不同。不是的子类型 我试图理解为什么它是坏的本质,并且刚刚读了关于LSP的文章。它有没有违反LSP?似乎没有明显的违规行为。
问题内容: 协方差(大致)是在使用它们的复杂类型中 镜像 “简单”类型的 继承 的能力。 例如,我们始终可以将的实例视为的实例。如果ComplexType是协变的,则可以将A 视为a 。 我想知道:协方差的“类型”是什么,它们与C#有什么关系(是否支持它们?) 代码示例将很有帮助。 例如,一种类型是Java支持的 返回类型covariance ,但C#不支持。 我希望有功能编程知识的人也能加入!
本文向大家介绍什么是偏差和方差?相关面试题,主要包含被问及什么是偏差和方差?时的应答技巧和注意事项,需要的朋友参考一下 泛化误差可以分解为偏差的平方加上方差加上噪声。 偏差度量了学习算法的期望预测和真实结果的偏离程度,刻画了学习算法本身的拟合能力 方差度量了同样大小的训练集的变动所导致的学习性能的变化,刻画了数据扰动所造成的影响 噪声表达了当前任务上任何学习算法所能达到的期望泛化误差下界,刻画了问