- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
首先,我阅读了很多关于 SO 的解释以及关于协变和逆变的博客,非常感谢 Eric Lippert在 Covariance and Contravariance 上制作了如此出色的系列.
不过,我有一个更具体的问题,我想稍微了解一下。
据我了解 Eric's explanation是协变和逆变都是描述转换的形容词。协变变换是保留类型顺序的变换,而逆变变换是反转它的变换。
我认为大多数开发人员都可以凭直觉理解协方差。
//covariant operation
Animal someAnimal = new Giraffe();
//assume returns Mammal, also covariant operation
someAnimal = Mammal.GetSomeMammal();
这里的返回操作是协变的,因为我们保留了 Animal 仍然大于 Mammal 或 Giraffe 的大小。关于这一点,大多数返回操作都是协变的,逆变操作没有意义。
//if return operations were contravariant
//the following would be illegal
//as Mammal would need to be stored in something
//equal to or less derived than Mammal
//which would mean that Animal is now less than or equal than Mammal
//therefore reversing the relationship
Animal someAnimal = Mammal.GetSomeMammal();
这段代码当然对大多数开发人员来说没有意义。
我的困惑在于逆变参数参数。如果你有这样的方法
bool Compare(Mammal mammal1, Mammal mammal2);
我一直了解到输入参数总是强制逆变行为。这样,如果该类型用作输入参数,则其行为应该是逆变的。
但是下面的代码有什么区别
Mammal mammal1 = new Giraffe(); //covariant
Mammal mammal2 = new Dolphin(); //covariant
Compare(mammal1, mammal2); //covariant or contravariant?
//or
Compare(new Giraffe(), new Dolphin()); //covariant or contravariant?
同样的道理,你不能做这样你不能做的事
//not valid
Mammal mammal1 = new Animal();
//not valid
Compare(new Animal(), new Dolphin());
我想我想问的是,是什么让方法参数通过逆变转换。
抱歉,这篇文章很长,可能是我理解有误。
编辑:
根据下面的一些对话,我了解到例如使用委托(delegate)层可以清楚地显示逆变。考虑以下示例
//legal, covariance
Mammal someMammal = new Mammal();
Animal someAnimal = someMammal;
// legal in C# 4.0, covariance (because defined in Interface)
IEnumerable<Mammal> mammalList = Enumerable.Empty<Mammal>();
IEnumerable<Animal> animalList = mammalList;
//because of this, one would assume
//that the following line is legal as well
void ProcessMammal(Mammal someMammal);
Action<Mammal> processMethod = ProcessMammal;
Action<Animal> someAction = processMethod;
当然这是非法的,因为有人可以将任何 Animal 传递给 someAction,而 ProcessMammal 期望任何 Mammal 或更具体(小于 Mammal)的东西。这就是为什么 someAction 只能是 Action 或任何更具体的 (Action)
然而,这在中间引入了一层委托(delegate),是否必须在中间有一个委托(delegate)才能发生逆变投影?如果我们将 Process 定义为接口(interface),我们会将参数参数声明为逆变类型只是因为我们不希望有人能够使用委托(delegate)执行我上面显示的操作?
public interface IProcess<out T>
{
void Process(T val);
}
最佳答案
更新:糟糕。事实证明,我在最初的回答中混淆了方差和“分配兼容性”。相应地编辑了答案。我还写了一篇博文,希望能更好地回答这些问题:Covariance and Contravariance FAQ
答案:我猜你第一个问题的答案是你在这个例子中没有逆变:
bool Compare(Mammal mammal1, Mammal mammal2);
Mammal mammal1 = new Giraffe(); //covariant - no
Mammal mammal2 = new Dolphin(); //covariant - no
Compare(mammal1, mammal2); //covariant or contravariant? - neither
//or
Compare(new Giraffe(), new Dolphin()); //covariant or contravariant? - neither
此外,这里甚至没有协方差。您所拥有的称为“分配兼容性”,这意味着您始终可以将派生程度更高的类型的实例分配给派生程度更低的类型的实例。
在 C# 中,数组、委托(delegate)和通用接口(interface)支持变体。正如 Eric Lippert 在他的博客文章中所说 What's the difference between covariance and assignment compatibility?是最好将方差视为类型的“投影”。
协变更容易理解,因为它遵循赋值兼容性规则(派生类型多的数组可以赋值给派生类型少的数组,“object[] objs = new string[10];”)。逆变颠倒了这些规则。例如,假设您可以执行类似“string[] strings = new object[10];”的操作。当然,由于显而易见的原因,您不能这样做。但那将是逆变(但同样,数组不是逆变的,它们仅支持协变)。
以下是来自 MSDN 的示例,我希望它们能向您展示逆变的真正含义(我现在拥有这些文档,所以如果您认为文档中有什么不清楚的地方,请随时给我反馈):
Using Variance in Interfaces for Generic Collections
Employee[] employees = new Employee[3];
// You can pass PersonComparer,
// which implements IEqualityComparer<Person>,
// although the method expects IEqualityComparer<Employee>.
IEnumerable<Employee> noduplicates =
employees.Distinct<Employee>(new PersonComparer());
// Event hander that accepts a parameter of the EventArgs type.
private void MultiHandler(object sender, System.EventArgs e)
{
label1.Text = System.DateTime.Now.ToString();
}
public Form1()
{
InitializeComponent();
// You can use a method that has an EventArgs parameter,
// although the event expects the KeyEventArgs parameter.
this.button1.KeyDown += this.MultiHandler;
// You can use the same method
// for an event that expects the MouseEventArgs parameter.
this.button1.MouseClick += this.MultiHandler;
}
Using Variance for Func and Action Generic Delegates
static void AddToContacts(Person person)
{
// This method adds a Person object
// to a contact list.
}
// The Action delegate expects
// a method that has an Employee parameter,
// but you can assign it a method that has a Person parameter
// because Employee derives from Person.
Action<Employee> addEmployeeToContacts = AddToContacts;
希望这对您有所帮助。
关于c# - 逆变解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1962629/
要在 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
我是一名优秀的程序员,十分优秀!