- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在阅读 C# 中的 Covariance
和 Contravariance
。
据我了解,
如果我们有一个类 Animal
和一个派生类 Cat
那么,
Covariance
特性使编译器接受将 Cat
类型对象传递给 Animal
类型对象,Contravariant
是副-反之亦然。
一切正常,直到我读到这一行。
“要注释类型协变,您可以使用 out
参数,对于逆变,您可以使用 in
参数”
根据我的说法,用 out
关键字修饰的参数 => 该值必须分配给函数中的特定参数。
我很难将 out
关键字关联到 covariance
并将 in
关键字关联到 contravariant
。
这两者有什么关系?两者都有 super 简单的例子吗?
提前致谢。
最佳答案
C# 4.0 中的协变和逆变都是指使用派生类而不是基类的能力。 in/out 关键字是编译器提示,指示类型参数是否将用于输入和输出。协方差
C# 4.0 中的协变由 out 关键字辅助,这意味着使用 out 类型参数的派生类的泛型类型是可以的。因此
IEnumerable<Fruit> fruit = new List<Apple>();
因为 Apple 是 Fruit,所以 List 可以安全地用作 IEnumerable逆变
逆变是 in 关键字,它表示输入类型,通常在委托(delegate)中。原理是一样的,就是delegate可以接受更多的derived class。
public delegate void Func<in T>(T param);
这意味着如果我们有一个 Func,它可以转换为 Func。
Func<Fruit> fruitFunc = (fruit)=>{};
Func<Apple> appleFunc = fruitFunc;
如果它们基本相同,为什么称为协变/逆变?
因为即使原则相同,从派生到基的安全转换,当用于输入类型时,我们可以安全地将派生程度较低的类型 (Func) 转换为派生程度较高的类型 (Func),这是有道理的,因为任何接受 Fruit 的函数也可以接受 Apple。
关于c# - out 关键字如何与类型协方差相关联?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19401739/
在我的设置中,我试图有一个界面 Table继承自 Map (因为它主要用作 map 的包装器)。两个类继承自 Table - 本地和全局。全局的将有一个可变的映射,而本地的将有一个只有本地条目的映射。
Rust Nomicon 有 an entire section on variance除了关于 Box 的这一小节,我或多或少地理解了这一点和 Vec在 T 上(共同)变体. Box and Vec
我是一名优秀的程序员,十分优秀!