c#协变和逆变实例分析
本文实例讲述了c#协变和逆变的原理及应用。分享给大家供大家参考。具体如下:
由子类向父类方向转变是协变,用out关键字标识,由父类向子类方向转变是逆变,用in关键字
协变和逆变的应用
一、 数组的协变
说明:声明的数组数据类型是animal,而实际上赋值时给的是dog数组;每一个dog对象都可以安全的转变为animal。dog向animal方法转变是沿着继承链向上转变的所以是协变
二. 委托中的协变和逆变
1、委托中的协变
public delegate animal getanimal();
//委托方法实现中的返回值是dog,是子类
static dog getdog(){return new dog();}
//getdog的返回值是dog, dog是animal的子类;返回一个dog肯定就相当于返回了一个animal;所以下面对委托的赋值是有效的
getanimal getmethod = getdog;
2、委托中的逆变
public delegate void feeddog(dog target);
//实际方法中的参数类型是animal
static void feedanimal(animal target){}
// feedanimal是feeddog委托的有效方法,因为委托接受的参数类型是dog;而feedanimal接受的参数是animal,dog是可以隐式转变成animal的,所以委托可以安全的的做类型转换,正确的执行委托方法;
feeddog feeddogmethod = feedanimal;
//定义委托时的参数是子类,实际上委托方法的参数是更宽泛的父类animal,是父类向子类方向转变,是逆变
三. 泛型委托的协变和逆变
1、 泛型委托中的逆变
public delegate void feed<in t>(t target);
//feed委托接受一个泛型类型t,注意在泛型的尖括号中有一个in关键字,这个关键字的作用是告诉编译器在对委托赋值时类型t可能要做逆变
//先声明一个t为animal的委托
feed<animal> feedanimalmethod = a=>console.writeline(“feed animal lambda”);
//将t为animal的委托赋值给t为dog的委托变量,这是合法的,因为在定义泛型委托时有in关键字,如果把in关键字去掉,编译器会认为不合法
feed<dog> feeddogmethod = feedanimalmethod;
2、泛型委托中的协变
public delegate t find<out t>();
//find委托要返回一个泛型类型t的实例,在泛型的尖括号中有一个out关键字,该关键字表明t类型是可能要做协变的
//声明find<dog>委托
find<dog> finddog = ()=>new dog();
//声明find<animal>委托,并将finddog赋值给findanimal是合法的,类型t从dog向animal转变是协变
find<animal> findanimal = finddog;
四. 泛型接口中的协变和逆变
1、泛型接口中的逆变
public interface ifeedable<in t>
{
void feed(t t);
}
//接口的泛型t之前有一个in关键字,来表明这个泛型接口可能要做逆变
//如下泛型类型feedimp<t>,实现上面的泛型接口;需要注意的是协变和逆变关键字in
public class feedimp<t>:ifeedable<t>
{
public void feed(t t){
console.writeline(“feed animal”);
}
}
//使用接口逆变:
ifeedable<dog> feeddog = new feedimp<animal>();
//上面的代码将feedimp<animal>类型赋值给了ifeedable<dog>的变量;animal向dog转变了,所以是逆变
2、泛型接口中的协变
public interface ifinder<out t>
{
t find();
}
//泛型接口的泛型t之前用了out关键字来说明此接口是可能要做协变的;如下泛型接口实现类
public class finder<t>:ifinder<t> where t:new()
{
public t find(){
return new t();
}
}
//使用协变,ifinder的泛型类型是animal,但是由于有out关键字,我可以将finder<dog>赋值给它
ifinder<animal> finder = new finder<dog>();
希望本文所述对大家的c#程序设计有所帮助。