什么是委托:
1.一切皆地址:在理解委托之前,要理解“一切皆地址”的意思,简单来说:
(1)变量(数据)是以某个地址为起点的一段内存中存储的值。
(2)函数(算法)是以某个地址为起点的一段内存中所存储的一组机器指令。
2.函数指针的升级版:在C语言中,可以定义一个函数指针,通过指向相关函数的地址,便能通过函数指针使用指向的函数。在C#中,可以把委托看作是函数指针的升级版,通过创建委托变量引用相关方法。
3.直接调用和间接调用:
(1)直接调用:通过函数名来调用函数,CPU通过函数名直接获得函数所在地址并开始执行->返回。
(2)间接调用:通过函数指针来调用函数,CPU通过读取函数指针存储的值获得函数所在地址并开始执行->返回。
总之,可以认为委托是持有一个或多个方法的对象。
委托概述:
1.声明委托类型:委托是一种类型,一般在类的外面声明,声明时要注意委托的返回类型和签名,因为返回类型和签名指定了委托能接受的方法的形式。
delegate int MyDel(int a, int b);
此代码声明了一个返回类型为int,包含两个int类型参数的委托,因此只能接受返回类型是int,并带有两个两个int类型参数的方法。
2.创建委托对象:委托是引用类型,因此有引用和对象。在创建委托对象时,要注意保存引用的方法返回类型和签名应与委托变量保持一致。
MyDel myDel = new MyDel(Add);//创建委托并保存引用
快捷语法如下:
MyDel myDel = Add;//创建委托并保存引用
3.给委托赋值:通过给委托赋值来改变包含在委托变量中的引用,旧的委托对象会被垃圾回收器回收。
MyDel myDel;
myDel = Add;//创建委托对象并赋值
myDel = Sub;//创建新的委托对象并赋值,同时旧的委托对象会被回收
4.组合委托:委托可以使用额外的运算符来“组合”,这个运算最终会创建一个新的委托。
MyDel myDel1 = Add;
Console.WriteLine(myDel1.GetHashCode());//27252167
MyDel myDel2 = Sub;
Console.WriteLine(myDel2.GetHashCode());//27252167
MyDel myDel3 = myDel1 + myDel2;
Console.WriteLine(myDel3.GetHashCode());//926573678
5.为委托添加方法:通过+=运算符为委托的调用列表添加方法,调用顺序是先添加先调用。
MyDel myDel = Add;
myDel += Sub;
myDel(1,2);//Add Sub
6.为委托移除方法:通过-=运算符为委托的调用列表移除方法,有以下注意事项:
(1)如果在调用列表中的方法有多个实例,-=运算符将从列表的最后开始搜索,并且移除第一个与方法匹配的实例。
(2)试图删除委托中不存在的方法将无效。
(3)试图调用空委托会抛出异常。
MyDel myDel = Add;
myDel += Sub;
myDel += Add;
myDel += Sub;
myDel += Sub;
myDel -= Sub;
myDel(1,2);//Add Sub Add Sub
7.调用带返回值的委托:如果委托有返回值并且在调用列表中一个以上的方法,则:
(1)调用列表中的最后一个方法返回的值就是委托调用返回的值。
(2)调用列表中所有其他方法的返回值都会被忽略。
delegate int MyDel(int a, int b);
static int Add(int x, int y)
{
return x + y;
}
static int Sub(int x, int y)
{
return x - y;
}
static void Main(string[] args)
{
MyDel myDel = Add;
myDel += Sub;
Console.WriteLine(myDel(1,2));//输出-1
}
8.调用带引用参数的委托:如果委托列表的方法带有引用参数,则:
(1)参数值会根据调用列表中的一个或多个方法的返回值而改变。
(2)参数执行方法后会传给下一个方法。
delegate void MyDel(ref int a);
static void Add2(ref int x)
{
x += 2;
}
static void Add3(ref int x)
{
x += 3;
}
static void Main(string[] args)
{
MyDel myDel = Add2;
myDel += Add3;
int x = 5;
myDel(ref x);
Console.WriteLine("{0}",x);//10
}