委托是一种数据结构,它引用静态方法或者引用类实例及该类的实例方法(MSDN);
委托类型的声明,建立了一个协定,该协定指向一个或者多个方法的签名;
委托是面向对象并且是类型安全的。
一、Delegate的简单例子:
委托的声明需要使用关键字:delegate;
委托的命名是任意的,但是委托必须与它指向的方法签名相匹配:返回类型、参数个数与类型。
namespace ConsoleApplication1
{
//定义委托,可以指向任何这样的方法:返回值 为 Int型,并且有两个Int参数
public delegate int MathDelegate(int x,int y);
public class DelegateDemo
{
public static int Add(int x, int y){returnx + y;}
public static int Multiply(int x, int y){returnx * y;}
public static int Subtract(int x, int y){returnx - y;}
}
public classProgram
{
static voidMain(string[] args)
{
//创建一个委托实例,指向DelegateDemo.Add()方法
MathDelegate math1 = newMathDelegate(DelegateDemo.Add); //调用Add()使用委托
Console.WriteLine("100 + 20 = {0}", math1(100, 20));
//创建一个委托实例,指向DelegateDemo.Multiply()方法
MathDelegate math2 = newMathDelegate(DelegateDemo.Multiply);
Console.WriteLine("100 * 20 = {0}", math2(100, 20));
Console.ReadLine();
}
}
}
二、委托的多播(Multicast)
多播是指一个委托对象可以指向多个方法,而不是仅仅是指向一个方法;
采用 += 添加方法,-= 移走方法
多播委托指向的方法的 返回值 一般是void,当然如果有返回值的话,那么仅能得到最后一个方法的返回值
namespace ConsoleApplication1 {
//定义委托,可以指向任何这样的方法:返回值 为 Int型,并且有两个Int参数
public delegate int MathDelegate(int x,int y);
public class DelegateDemo
{
public static int Add(int x, int y)
{
Console.WriteLine("加法的结果:");
Console.WriteLine("{0} + {1} = {2}
", x, y, x + y);
return x + y;
}
public static int Multiply(int x, int y)
{
Console.WriteLine("乘法的结果:");
Console.WriteLine("{0} * {1} = {2}
", x, y, x * y);
return x * y;
}
public static int Subtract(int x, int y)
{
Console.WriteLine("减法的结果:");
Console.WriteLine("{0} - {1} = {2}
", x, y, x - y);
return x - y;
}
}
public class Program
{
static void Main(string[] args)
{
//创建一个委托实例,指向DelegateDemo.Add()方法
MathDelegate math = new MathDelegate(DelegateDemo.Add);
//使用上述创建的相同的实例,调用DelegateDemo.Multiply()方法 和 DelegateDemo.Subtract()方法
math += new MathDelegate(DelegateDemo.Multiply);
math += new MathDelegate(DelegateDemo.Subtract);
int result = math(100, 20);
Console.WriteLine("委托调用结果:{0}",result);
Console.ReadLine();
}
}
}
三、委托协变和逆变
将方法签名与委托类型匹配时,协变和逆变可以提供一定程度的灵活性;
协变允许方法具有的派生返回类型比委托中定义的更多;
逆变允许方法具有的派生参数类型比委托类型中的更少;(MSDN)
namespace ConsoleApplication1
{
public delegate Person PersonDelegate();
public class DelegateCovariance
{
public static Person GetPerson() { return new Person(); }
public static Student GetStudent() { return new Student(); }
static void Main(string[] args)
{
PersonDelegate personDelegate = new PersonDelegate(GetPerson);
Person person = personDelegate();
Console.WriteLine("Person:{0}", person.ToString());
PersonDelegate studentDelegate = new PersonDelegate(GetStudent);
Student student = (Student)studentDelegate();//如果没有强类型转换,则不能通过编译
Console.WriteLine("Student:{0}", student.ToString());
Console.ReadLine();
}
}
public class Person
{
protected string _firstName;
protected string _lastName;
protected int _age;
public Person()
{
this._firstName = "Smith";
this._lastName = "Jack";
this._age = 20;
}
public override string ToString()
{
return string.Format("FirstName:{0} LastName:{1} Age:{2}", _firstName, _lastName, _age);
}
}
public class Student : Person
{
protected string _height;
public Student() : base() { _height = "175cm"; }
public override string ToString()
{
return string.Format("FirstName:{0} LastName:{1} Age:{2} Height:{3}", _firstName, _lastName, _age, _height);
}
}
}