作者fo40225 ()
标题Re: [问题] C# 泛型中的共变数和反变数
时间Sun Apr 2 02:24:57 2017
※ 引述《LaPass (LaPass)》之铭言:
: https://pastebin.com/5xXiWRPB
: 如连结中的程式码
: 所以即使知道 actd 实际上是一个 Action<C>
: 在 C# 当中也没有任何方法可以把他转换回 Action<C>
: 是这样子吗?
https://msdn.microsoft.com/en-us/library/dd799517.aspx
Action泛型委派的宣告如下
public delegate void Action<in T>(T obj);
in T 代表的是T是一个contravariance反变数
简单的说 这个T是一个"输入"参数类型
假设我们有两个class
public class Base {}
public class Derived : Base {}
宣告一个 Action<Base> foo 表示这个委派 foo 接受一个 Base 实体
这时候在泛型宣告有 in 限定词的情况下
可以直接 Action<Derived> bar = foo;
因为能给 bar 的 Derived 一定是一个 Base 这是类型安全的
而你的范例 Action<Base> foo = bar;
这句话并不是类型安全 能接受Derived输入 不代表能接受输入Base
所以需要显式地cast
相对於Contravariance反变数的是Covariance共变数
范例
IEnumerable泛型介面的宣告如下
public interface IEnumerable<out T>
out T代表着T是一个"输出"参数类型
宣告一个 IEnumerable<Derived> foo 表示这个介面是输出一个Derived
在泛型宣告有out限定词的情况下
IEnumerable<Base> bar = foo; 这句话是类型安全的
输出一个Derived一定是Base
这时候不用特别转换
结论 如果编译器告诉你错了 就要小心是不是有什麽地方搞错了
做cast时要了解自己在做什麽 不然能编译成功也会在runtime时炸掉
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 61.228.29.213
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_Sharp/M.1491071103.A.86E.html
1F:推 Litfal: 我觉得Covariance和Contravariance这两个词实在难懂, 04/02 17:07
2F:→ Litfal: 修饰关键字的out和in就又短又好懂XD 04/02 17:08
3F:推 kalaja: 共变数与反变数确实有点艰涩,很容易忘记。 04/02 21:54
4F:推 LaPass: 推 04/03 01:33