1

我正在阅读 C# 中的Covarianceand Contravariance

据我了解,

如果我们有一个类Animal和一个派生类Cat,那么,

Covariance功能使编译器接受将类型对象传递给Cat类型Animal对象,Contravariant反之亦然。

一切都很好,直到我读到这一行。

“要注释类型协方差,请使用out参数,而对于逆变,请使用in参数”

根据我的说法,用out关键字修饰的参数 => 必须将值分配给函数中的特定参数。

我很难将out关键字covariancein关键字关联起来contravariant

这两者有什么关系?两者都有什么超级简单的例子吗?

提前致谢。

4

4 回答 4

2

C# 4.0 中的协变和逆变都指的是使用派生类而不是基类的能力。in/out 关键字是编译器提示,用于指示类型参数是否将用于输入和输出。协方差

C# 4.0 中的协变由 out 关键字辅助,这意味着使用 out 类型参数的派生类的泛型类型是可以的。因此

IEnumerable<Fruit> fruit = new List<Apple>();

由于 Apple 是水果,因此 List 可以安全地用作 IEnumerable 逆变器

逆变是 in 关键字,它表示输入类型,通常在委托中。原理是一样的,就是delegate可以接受更多的派生类。

public delegate void Func<in T>(T param);

这意味着如果我们有一个 Func,它可以转换为 Func。

Func<Fruit> fruitFunc = (fruit)=>{};
Func<Apple> appleFunc = fruitFunc;

如果它们基本上是相同的,为什么它们被称为协/逆变?

因为即使原理相同,从派生到基的安全转换,当用于输入类型时,我们可以安全地将派生较少的类型 (Func) 转换为派生较多的类型 (Func),这是有道理的,因为任何函数即取Fruit,也可取Apple。

于 2013-10-16T11:09:04.227 回答
1

out是一个上下文关键字,即根据它的位置,它意味着不同的东西。
您正在谈论参数修饰符。但就协变和逆变而言,情况并非如此。在泛型接口定义中使用关键字时,它是泛型修饰符,完全是另外一回事。

于 2013-10-16T11:12:52.353 回答
1

out关键字有不同的用途。正如您在“泛型类型参数”的上下文中所指出的,它充当使“协方差”起作用的关键字,另一个用途类似于ref我们用来从 a 获取多个返回值的关键字Method

如果您查看MSDN中的out-keywordout文档,将列出关键字的两个用途。不要混淆,它会根据上下文而有所不同。

您也可以找到与关键字的相似之处new,它也有不同的用途。AFAIK 他们是

  1. 创建一个类的新实例。object obj = new object();
  2. 显式地隐藏基类方法或属性。protected new void BaseMethod(){}
  3. 通用参数约束。private void MyGenericMethod<T>(T t) where T:new()
于 2013-10-16T11:17:34.480 回答
1

我认为微软的人通过使用不明确的功能名称和功能参数的不好关键字使这个功能变得非常复杂。

我从向量的协方差和逆变(数学)中知道了这个名字,当我第一次在 C# 中听到它时,我感到震惊!

@JoesphAlbahari 在他的书 C# 4 In a Nutshell 中很好地解释了这个主题,第 109-112 页。我建议你真的阅读它。

于 2013-10-16T11:49:36.713 回答