Re: [问题] C# 泛型中的共变量和反变量

楼主: fo40225   2017-04-02 02:24:57
※ 引述《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时炸掉
作者: Litfal (Litfal)   2017-04-02 17:07:00
我觉得Covariance和Contravariance这两个词实在难懂,修饰关键字的out和in就又短又好懂XD
作者: kalaja (菸酒生)   2017-04-02 21:54:00
共变量与反变量确实有点艰涩,很容易忘记。
作者: LaPass (LaPass)   2017-04-03 01:33:00

Links booklink

Contact Us: admin [ a t ] ucptt.com