- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我需要有关泛型和委托(delegate)方差的更多信息。以下代码片段无法编译:
Error CS1961 Invalid variance: The type parameter 'TIn' must be covariantly valid on 'Test.F(Func)'. 'TIn' is contravariant.
public interface Test<in TIn, out TOut>
{
TOut F (Func<TIn, TOut> transform);
}
.net Func
定义如下:
public delegate TResult Func<in T, out TResult> (T arg);
为什么编译器提示 TIn
是逆变的,而 TOut
是协变的,而 Func 期望完全相同的方差?
编辑
对我来说主要的限制是我希望我的测试接口(interface)有 TOut 作为协变,以便像这样使用它:
public Test<SomeClass, ISomeInterface> GetSomething ()
{
return new TestClass<SomeClass, AnotherClass> ();
}
鉴于 public class AnotherClass : ISomeInterface
。
最佳答案
I need more information about variance in generics and delegates.
我写了一系列关于此功能的博客文章。尽管其中一些已经过时——因为它是在设计定稿之前编写的——但那里有很多有用的信息。特别是如果您需要方差有效性的正式定义,您应该仔细阅读:
https://blogs.msdn.microsoft.com/ericlippert/2009/12/03/exact-rules-for-variance-validity/
有关相关主题,请参阅我在 MSDN 和 WordPress 博客上的其他文章。
Why the compiler complains about TIn being contravariant and TOut - covariant while the Func expects exactly the same variance?
让我们稍微重写一下代码看看:
public delegate R F<in T, out R> (T arg);
public interface I<in A, out B>{
B M(F<A, B> f);
}
编译器必须证明这是安全,但事实并非如此。
我们可以通过假设它是安全的来说明它是不安全的,然后发现它是如何被滥用的。
假设我们有一个具有明显关系的动物层次结构,例如,哺乳动物是一种动物,长颈鹿是一种哺乳动物,等等。假设您的差异注释是合法的。我们应该能够说:
class C : I<Mammal, Mammal>
{
public Mammal M(F<Mammal, Mammal> f) {
return f(new Giraffe());
}
}
我希望您同意这是一个完全有效的实现。现在我们可以这样做:
I<Tiger, Animal> i = new C();
C
工具 I<Mammal, Mammal>
,我们说过第一个可以变得更具体,第二个可以变得更一般,所以我们做到了。
现在我们可以这样做:
Func<Tiger, Animal> f = (Tiger t) => new Lizard();
对于这个代表来说,这是一个完全合法的 lambda,它与以下人的签名相匹配:
i.M(f);
然后会发生什么? C.M
期待一个接受长颈鹿并返回哺乳动物的函数,但它被赋予了一个接受老虎并返回蜥蜴的函数,所以有人会有非常糟糕的一天。
显然,这种情况是不允许发生的,但是沿途的每一步都是合法的。我们必须得出结论,方差本身并不能证明是安全的,事实上,事实并非如此。编译器拒绝这一点是正确的。
获得正确的差异不仅仅是简单地匹配输入和输出注释。 您必须以不允许此类缺陷存在的方式这样做。
这解释了为什么这是非法的。为了解释如何它是非法的,编译器必须检查B M(F<A, B> f);
是否符合以下条件。 :
B
是协变有效的。既然它被宣布为“out”,它就是。F<A, B>
逆变有效。它不是。泛型委托(delegate)的“逆变有效”定义的相关部分是:如果第 i 个类型参数被声明为逆变,则 Ti 必须是协变有效的。 好的。第一个类型参数,T
, 被宣布为逆变的。因此第一个类型参数 A
必须协变有效。但它不是协变有效的,因为它被声明为逆变的。这就是你得到的错误。同样,B
也很糟糕,因为它必须逆变地有效,但是 B
是协变的。编译器在这里发现第一个问题后不会继续寻找其他错误;我考虑过它,但拒绝了它,因为它是一条过于复杂的错误消息。我还注意到,即使委托(delegate)不是变体,您仍然会遇到这个问题;在我的反例中,我们没有在任何地方使用 F 在其类型参数中是可变的这一事实。如果我们尝试会报类似的错误
public delegate R F<T, R> (T arg);
相反。
关于c# - 泛型中 Func 的协变和逆变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48177452/
要在 R 中绘制正态分布曲线,我们可以使用: (x = seq(-4,4, length=100)) y = dnorm(x) plot(x, y) 如 dnorm将 y 计算为 x 的函数,R 是否
@XmlTransient 阻止将 JavaBeans 属性映射到 XML 表示。是否存在与此相反的情况,这意味着即使 WebService 未使用的方法也会被映射?如果这不可能,是否存在解决方法?
我有以下键数组: var keys = [{userId: "333"}, {userId: "334"}] 这个对象数组: var users = [ {id: "333", firstName:
我正在寻找将字符串转换为类型的通用方法。 例如: class SomeThing { public void Add(T value) { //... } pub
我看到了this question , 并弹出这个想法。 有没有一种在 PHP 中执行此操作的有效方法? 编辑 有演示最好吗? 最佳答案 你可以使用 pear 包 Math_Matrix为此。 关于矩
如何在 python 中求逆矩阵?我自己实现了它,但它是纯 python,我怀疑那里有更快的模块可以做到这一点。 最佳答案 你应该看看 numpy如果您进行矩阵操作。这是一个主要用C语言编写的模块,比
是否有比使用 IF ELSE 构造更简单的方法来反转 bool 值? 通常我会使用! bool 值前面。但这在 Navision 中不起作用 最佳答案 您可以使用 NOT 关键字代替 !。 关于nav
假设我有一个对象响应。现在我想检查一个 bool 变量,success,在 Response 下并做一个早期返回是 response 不成功。 if(response == null || !resp
任何人都可以提供/引用多维行主要顺序的“索引->偏移”*转换的倒数。此外,(伪)代码将不胜感激。 http://en.wikipedia.org/wiki/Row-major_order 举个例子,简
我有一个看起来像这样的系统: z1 = 5*x1 + x2*cos(x3) z2 = x1*sin(x3) + 3*x2 z3 = 3*x1 - 2*x2 这是微分方程组的变换(只是为了提供一些背景信
我正在使用org.apache.commons.math3.transform类FastFourierTransformer,我现在尝试在真实数据集上应用FFT,并应用逆FFT来获取原始数据集。我的问
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
背景 我需要使用已知的累积分布函数 (CDF) 从相当复杂的概率密度函数 (PDF) 中随机采样,并且我正在尝试使用 inverse transform sampling 。这应该很容易做到,因为我有
是否有任何 System.identityHashCode (object) 的逆函数能够从 System.identityHashCode (object) 的结果中提供对象的值? 最佳答案 Sys
有没有办法在mysql中获取group by语句的逆?我的用例是删除所有重复项。 假设我的表格如下所示: ID | columnA | ... 1 | A 2 | A 3 | A 4
我有一个查询,它给我一个公司列表(tblprov)及其相应的类别(tblrubro) 两个表通过查找表 (tblprovxrubro) 相关 SELECT p.id, p.name, r.idCat,
我有一个 jpg 图像,在矩形中有一个圆形物体,我想使圆形物体的环境透明... (本例去除红色区域) 借助这个iOS make part of an UIImage transparent和“UIBe
我想知道是否可以在不需要临时数组的情况下通过 Cholesky 分解获得矩阵的逆。截至目前,我可以在不使用临时数组的情况下进行 cholesky 分解,但从那里我还没有想出一种方法来获得原始矩阵的逆矩
是否可以在 Angular 中使用逆$watch? 我的问题 我使用 Angular-translate,并且我想对每个缺少的翻译使用 $http.put 。但我收到此错误: "10 $digets(
我正在执行 radix-2 dif 逆 fft。我正在使用共轭和缩放的属性来返回结果。我共轭我的输入 vector ,执行常规 radix-2 fft(不是 ifft),共轭结果,然后按 1.0/N
我是一名优秀的程序员,十分优秀!