协变:协变允许所调用方法的返回类型可以是委托的返回类型的派生类型,当委托方法的返回类型具有的派生类型比委托签名更大时,就成为协变委托方法。因为方法的返回类型比委托签名的返回类型更具体,所以可对其进行隐式转换。
逆变:逆变允许将带有派生参数的方法用作委托,当委托签名具有一个或多个参数,并且这些参数的类型派生自方法参数的类型时,就成为逆变委托方法。因为委托方法签名参数比方法参数更具体,所以可以在传递给处理程序方法时对它们进行隐式转换。
代码示例:
声明委托和需要使用的类
public delegate Person PointPerson(int i);//声明委托,返回第i个人
public delegate int Position(Student s);//声明委托,返回指定学生的位置
public class Person
{
public string name;
public char sex;
public Person(string n, char s)
{
name = n;
sex = s;
}
}
public class Student:Person //派生类
{
public string school;
public Student(string n, char s, string sch)
: base(n, s)
{
school = sch;
}
}
创建人的集合类和学生的集合类
public class Persons //若干个人的集合
{
public Person[] p = new Person[3];//创建3个人的集合
public Person getPetson(int i) //得到指定位置的人,Persons中的方法
{
if (i < 0 || i > p.Length)
return p[0];
else
return p;
}
public int getPos(Person per) //返回指定人的位置,Persons中的方法
{
int k = -1;
for (int i = 0; i < p.Length; i++)
{
if (p.name == per.name && p.sex == per.sex)
{
k = i;
break;
}
}
return k;
}
}
public class Students //若干个学生的集合
{
public Student[] s = new Student[3];
public Student getStudent(int i) //得到指定位置的学生,Students中的方法
{
if (i < 0 || i > s.Length)
return s[0];
else
return s;
}
public int getPos(Student stu) //得到指定学生的位置,Students中的方法
{
int k = -1;
for (int i = 0; i < s.Length; i++)
{
if (s.name == stu.name && s.sex == stu.sex)
{
k = i;
break;
}
}
return k;
}
}
主函数中使用
class Program
{
static void Main(string[] args)
{
//创建学生集合并存入3个学生的数据
Students stus = new Students();
stus.s[0] = new Student("tom", '男', "电子科技大学");
stus.s[1] = new Student("david", '男', "清华大学");
stus.s[2] = new Student("lily", '女', "北京大学");
//创建返回值为Person类型的委托对象并指定引用Students集合的getStudent方法
PointPerson point = new PointPerson(stus.getStudent);
for (int i = 0; i < 3; i++)
{
Person p = point(i); //协变方法调用
Console.WriteLine("姓名:{0} 性别:{1}", p.name, p.sex);
}
//创建人集合并存入3个人的数据
Persons pers = new Persons();
pers.p[0] = new Person("tom", '男');
pers.p[1] = new Person("david", '男');
pers.p[2] = new Person("lily", '女');
//创建参数为Students的委托对象,并指定引用Persons集合的getPos方法
Position position = new Position(pers.getPos);
int k = position(stus.s[2]); //逆变委托方法调用
Console.WriteLine("这个学生在persons中是第{0}个人", k + 1);
Console.ReadKey();
}
}
|