委托
委托是函数的封装,它代表一类函数,它们都符合一定的签名:拥有相同的参数列表和返回值类型。同时,委托也可以看成是对函数的抽象,是函数的”类”。
此时,委托的实例将代表一个具体的函数。
一个委托声明、定义了一个引用类型可以用来封装具有一定签名的方法。一个委托实例可用来封装一个静态或实例方法。
一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值
更加灵活的方法调用
用于异步回调
多线程编程中使用委托来指定启动一个线程时调用的方法
public delegate void ThreadStart(); //委托
static void DoCompress() //方法实例
{
//压缩代码
}
ThreadStart entryPoint = new ThreadStart(DoCompress);
Thread compressThread = new Thread(entryPoint);
委托应用——异步回调
异步回调:由于实例化委托是一个对象,所以可以将其作为参数进行传递,也可以将其赋值给属性。这样,方法便可以将一个委托作为参数来接受,并且以后可以调用该委托。这称为异步回调,是在较长的进程完成后用来通知调用方的常用方法。以这种方式使用委托时,使用委托的代码无需了解有关所用方法的实现方面的任何信息
using System;
delegate bool CompareOp(object a, object b); //声明委托类型
class BubbleSorter
{
static public void Sort(object[] sortArray, CompareOp co)
{
for (int i = 0; i < sortArray.Length; i++) //使用传进来的函数比较,进行定制化的排序
{
for (int j = 0; j < i; j++)
{
if (co(sortArray[j], sortArray[i]))
{
object temp = sortArray[i];
sortArray[i] = sortArray[j];
sortArray[j] = temp;
}
}
}
}
}
class Employee
{
private string name;
private decimal salary;
public Employee(string name, decimal salary)
{
this.name = name;
this.salary = salary;
}
public override string ToString()
{
return string.Format(name + ",{0:C}", salary);
}
public static bool Compare(object e1, object e2)
{
Employee ee1 = (Employee)e1;
Employee ee2 = (Employee)e2;
return (ee1.salary > ee2.salary) ? true : false;
}
}
class Test
{
static void Main(string[] args)
{
Employee[] employees ={ new Employee("王平", 2000), new Employee("李明", 1970), new Employee("孙丽", 1800), new Employee("付新", 1950), new Employee("林笑", 1900) };
CompareOp EmployeeCompareOp = new CompareOp(Employee.Compare);
BubbleSorter.Sort(employees, EmployeeCompareOp);
for (int i = 0; i < employees.Length; i++)
Console.WriteLine(employees[i].ToString());
}
}
如何委托
委托是面向对象的,是引用类型,对委托的使用要先定义后实例化,才能调用
delegate int SomeDelegate(int nID, string sName);
SomeDelegate d1=new SomeDelegate(wr.InstanceMethod);
d1(5,”aaa”);
委托实例化的实参方法中的参数和返回类型必
须和委托的定义一致
委托实例化中的参数可以是非静态方法,也可
以是静态方法
using System;
class SimpleClass
{
public class WorkerClass
{
public int InstanceMethod(int nID, string sName)
{
int retval = 0;
retval = nID * sName.Length;
Console.WriteLine("调用InstanceMethod方法");
return retval;
}
static public int StaticMethod(int nID, string sName)
{
int retval = 0;
retval = nID * sName.Length;
Console.WriteLine("调用StaticMethod方法");
return retval;
}
}
public delegate int SomeDelegate(int nID, string sName);
static void Main()
{
//调用实例方法
WorkerClass wr = new WorkerClass();
SomeDelegate d1 = new SomeDelegate(wr.InstanceMethod);
Console.WriteLine("Invoking delegate InstanceMethod, return={0}", d1(5, "aaa"));
//调用静态方法
SomeDelegate d2 = new SomeDelegate(WorkerClass.StaticMethod);
Console.WriteLine("Invoking delegate StaticMethod, return={0}", d2(5, "aaa"));
}
}
可以在类的任何地方定义委托,既可以在一个类的内部定义,也可以在类的外部定义,还可以在命名空间中将委托定义为顶层对象
可以给委托定义添加修饰符public、private和protected委托派生于System.Delegate,在语法上总是带有一个参数构造函数,这个参数就是委托引用的方法,这个方法必须匹配最初定义委托时的签名。
委托与C++函数指针的区别
委托可以指向多个
方法
当我们唤起一个搭载了多个方法的delegate,所有方法以其被搭载的顺序被依次唤起
委托搭载的所有方法可以不属于同一个类,但必须具有相同的原型,方法可以是静态的或非静态的
namespace myDelegate
{
public delegate void SendableDelegate( string s);
public class Subscriber
{
public string name;
public Subscriber( string name)
{
this.name = name;
}
public void PutNewsPaperIn( string s)
{
Console.WriteLine( "{0} 在报箱里收到送来的 {1}" , name, s);
}
public void PutMilkIn( string s)
{
Console.WriteLine( "{0} 在奶箱里收到送来的 {1}" , name, s);
}
}
public class NewsPaperSender
{
// 委托实现
public event SendableDelegate SendNewsPaperHandler;
public void SendNewsPaper()
{
if (SendNewsPaperHandler != null)
SendNewsPaperHandler( " 报纸 " );
}
public void Subscribe( SendableDelegate sd)
{
SendNewsPaperHandler += sd;
}
}
public class MilkSender
{
// 委托实现
public event SendableDelegate SendMilkHandler;
public void SendMilk()
{
if (SendMilkHandler != null)
SendMilkHandler( " 牛奶 " );
}
public void Subscribe( SendableDelegate sd)
{
SendMilkHandler += sd;
}
}
// 功能的实现
public class Client
{
public static void Main( string[] args )
{
// 委托实现
MilkSender ms = new MilkSender();
NewsPaperSender nps = new NewsPaperSender();
Subscriber s1 = new Subscriber( " 张三 " );
Subscriber s2 = new Subscriber( " 李四 " );
Subscriber s3 = new Subscriber( " 王五 " );
ms.Subscribe( new SendableDelegate(s1.PutMilkIn));
ms.Subscribe( new SendableDelegate(s2.PutMilkIn));
nps.Subscribe( new SendableDelegate(s2.PutNewsPaperIn));
nps.Subscribe( new SendableDelegate(s3.PutMilkIn));
ms.SendMilk();
nps.SendNewsPaper();
}
}
}