C#学习笔记
委托的基本知识
委托
委托实际上是一种数据类型,我们可以使用它来定义变量。
一个委托类型的变量,可以引用任何一个满足其要求的方法(包括静态或实例方法)
委托变量有点像时一个方法的“容器”,将某一个具体的方法“装入”之后,这个委托变量就可以当成方法一样调用。
例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 委托
{
public class MathOpt
{
public int Add(int x,int y)
{
return x + y;
}
public static int Max(int x,int y)
{
return (x > y || x == y) ? x : y;
}
}
//声明一个委托方法
public delegate int MathOptDelegate(int value1, int value2);
class Program
{
static void Main(string[] args)
{
MathOptDelegate oppDel;
//委托时一种用户自定义的数据类型,可以用于自定义变量
MathOpt obj = new MathOpt();
//oppDel = obj.Add;
//也可以接收偶一个静态方法的引用
oppDel = MathOpt.Max;
//委托变量可以当成普通方法那样调用
Console.WriteLine(oppDel(1,2));
//可以把方法引用直接传给委托类型的参数
Console.WriteLine(UseDelegate(obj.Add,10,20));
Console.WriteLine(UseDelegate(MathOpt.Max,100,200));
Console.ReadKey();
}
//可以定义委托类型的参数
static int UseDelegate(MathOptDelegate option, int x, int y)
{
return option(x, y);
}
}
}
组合委托
委托可以使用额外的运算符来组合,这个运算符会创建一个新的委托。
例如1
2
3MathOptDelegate oppDelA = MathOpt.Max;
MathOptDelegate oppDelB = obj.Add;
MathOptDelegate oppDelC = oppDelA + oppDelB;
oppDelC成为一个具有组合调用列表的新委托。
为委托添加和减去方法
可以使用+=运算符为委托添加方法
例:1
2MathOptDelegate oppDelA = MathOpt.Max;
oppDelA += obj.Add; //添加方法
由于委托不可变,使用+=运算符时,实际上是创建了一个新委托
可以使用-=运算符为委托移除方法1
oppDelA -= obj.Add; //移除方法
与增加方法一样,其实是创建了一个新委托,新委托是旧委托的副本
综合举例:
1 | using System; |
运行结果:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17del1的委托调用列表中包含2个方法。
Func1: i=5
Func2: i=10
del2的委托调用列表中包含2个方法。
Func1: i=5
Func2: i=10
合并del1和del2后,新的委托变量mul的委托调用列表中包含4个方法。
Func1: i=10
Func2: i=20
Func1: i=10
Func2: i=20
合并之后,新的委托变量mul的返回值 = 20
移除Func2后,委托变量mul包含3个方法。
Func1: i=10
Func2: i=20
Func1: i=10
移除Func2后,返回值 = 10
注:
如果调用列表中的方法有多个实例,-=运算符将从列表最后开始搜索,并移除第一个与方法匹配的实例。
试图删除委托中不存在的方法是没有效果的。
试图调用空委托会抛出异常,通常与null比较判断是否为空。
如果一个方法在调用列表中出现多次,当委托被调用时,每次在列表中遇到这个方法时他都会被调用一次。
如果委托有返回值并且在列表中有一个以上的方法,调用列表中最会一个方法返回的值就时委托调用的返回值,其它数值都会被忽略。
引用参数值会在调用期间发生改变。
另一个例子
1 | using System; |
说明:
Timer构造函数第一个参数TimerCallback,定时引用的函数就是这么一个函数引用的
可以看出在.Net基类库中,可以明显看出TimerCallback是一个委托,返回void,接受一个object参数,同样就可以编写一个
void ShowTime(Object ti)
函数