码迷,mamicode.com
首页 > Web开发 > 详细

.NET 泛型中的逆变 和 协变

时间:2018-06-24 23:42:41      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:关键字   接受   int   4.0   告诉   意思   版本   原因   class   

逆变和协变是.net 4.0 版本中推出了的概念, 只能在泛型委托 和 泛型接口中使用,

当我们在给泛型变量赋值的时候, 如果赋值表达式看着很安全和谐就是协变, 反之就是逆变

1. 协变 (out)

我们都知道泛型接口的泛型参数不一样时, 默认情况下是不能赋值的, 就算参数存在继承关系也是不行的

如下:

 

1 Interface1<string> obj1 = null;
2 
3 Interface1<object> obj2 = obj1
4 
5 // 这个赋值操作是不允许的, obj1 和 obj2是两个完全不相同的对象

 

如果接口的泛型参数标注为协变了, 那么就可以使表达式成立, 前提泛型参数之间存在继承关系

如下:

 1 // 定义接口
 2 
 3 Interface Interface1<out T>{
 4 
 5 }
 6 
 7 // 在这种情况下表达式是成立的
 8 
 9 Interface1<string> obj1 = null;
10 
11 Interface1<object> obj2 = obj1

 

接口的泛型参数标注为协变, 那么在接口定义的时候 这个泛型参数就不能作为入参传入,  至于原因如下

 1 // 定义接口
 2 
 3 Interface Interface1<out T>{
 4 
 5 }
 6 
 7 
 8 
 9 Interface1<string> obj1 = null;
10 
11 Interface1<object> obj2 = obj1
12 
13  
14 
15 // 如果我们在Interface1 接口中定义了一个 void Add<T>(T obj) 方法
16 
17 // 那么 obj2.Add(123)  这个语句就可以成立, 但是obj2 实际上指向是一个Interface1<string> 对象, Add 方法也只能接收一个string 的值, 那个这个方法的调用就不是安全的了, 会出现异常
18 
19 // 所以微软的协变使用out 作为关键字也是在说out 标注的参数只能用于返回不能用于输入

 逆变(in)

 逆变的定义就是字面意思 很违和的看着不安全的变化, 那么逆变我们在什么时候使用呢, 逆变的应用场景一般就是我们使用委托的时候用

 1 // 如我们定义了一个委托
 2 
 3 delegate void DelegateTest <T>(T obj);
 4 
 5 // 定位委托变量
 6 DelegateTest<object> dt1 = obj =>{};
 7 
 8 // 委托DelegateTest 只有入参没有返回值
 9 // 那么我们可不可以进行下列操作呢
10 
11 DelegateTest<string> dt2 = dt1 
12 
13 // 按道理这个操作是安全的  dt1 接受一个object 类型的入参, 我们使 dt2 = dt1 那么我们调用委托的时候 dt2("abc")  "abc" 符合dt1的入参类型 object 才对的, 为什么会不行呢
14 // 这是因为 dt1  和 dt2 是两个完全不相同的委托, 和 案例1 中的情况是一样的
15 
16 // 如果我们定义委托的时候T标注为逆变这个赋值表达式就可以成立了
17 delegate void DelegateTest <in T>(T obj);
18 // 标注逆变的作用就是告诉编译器, 我这个参数只会作为入参, 不会作为返回值, 起约束作用

 

同时使用逆变和协变的案例:

// 我们C# 中的  系统委托 Func 就是同时使用逆变和协变的

// Func 委托的定义
public delegate TResult Func<in T, out TResult>(T arg);

Func<object, string> fuc1 = obj => obj.ToString();
Func<string, object> fuc2 = fuc1;
            
string obj1 = fuc1(123);
object obj2 = fuc2("abc");

 

 

.NET 泛型中的逆变 和 协变

标签:关键字   接受   int   4.0   告诉   意思   版本   原因   class   

原文地址:https://www.cnblogs.com/mirck/p/5801030.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!