Appearance
委托
概念与理解
类似于C++中的函数指针,委托是对方法的引用(所以其是一种引用类型变量),常用于实现事件和回调方法,并均派生自System.Delegate类。
先看一个例子:
csharp
using System;
delegate int NumberChanger(int n);
namespace DelegateAppl
{
class TestDelegate
{
static int num = 10;
public static int AddNum(int p)
{
num += p;
return num;
}
public static int MultNum(int q)
{
num *= q;
return num;
}
public static int getNum()
{
return num;
}
static void Main(string[] args)
{
// 创建委托实例
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
// 使用委托对象调用方法
nc1(25);
Console.WriteLine("Value of Num: {0}", getNum());
nc2(5);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}
直接看Main里的实例与调用,看到 NumberChanger 被实例化为nc1和nc2,此时AddNum和MultNum在 NumberChanger 中。然后通过实例化的nc1和nc2进行调用,达到一般函数调用一样的效果。
所以感觉上,委托像是伪装了的一层函数,通过伪装,代行函数的职能。“委托”这个翻译也很到位,就是一个函数的功能被委托给了委托类型的变量。
多播(组播)
一个委托调用了多个方法,这种委托称为多播委托。
csharp
public class App
{
delegate int DNumChange(int a, int b);
static int numAdd(int a, int b)
{
Console.WriteLine("Add: {0}", a + b);
return a + b;
}
static int numMinus(int a, int b)
{
Console.WriteLine("Minus: {0}", a - b);
return a - b;
}
static void Main(string[] args)
{
DNumChange nc = numAdd;
nc += numMinus; // 委托中添加方法
// nc -= numAdd; // 委托中去掉方法
nc(3,2);
Console.ReadKey();
}
}
委托如果不指向任何方法会报错,所以使用前要判断一下。关键词:GetInvocationList
Delegate[] delegates = nc.GetInvocationList();
下面是通过遍历的方式去调用委托中的方法:
csharp
public class App
{
delegate int DNumChange(int a, int b);
static int numAdd(int a, int b)
{
Console.WriteLine("Add: {0}", a + b);
return a + b;
}
static int numMinus(int a, int b)
{
Console.WriteLine("Minus: {0}", a - b);
return a - b;
}
static void Main(string[] args)
{
DNumChange nc = numAdd;
nc += numMinus;
Delegate[] delegates= nc.GetInvocationList();
foreach (Delegate d in delegates)
{
d.DynamicInvoke(3,2); // 不要忘记写参数
}
Console.ReadKey();
}
}
Action委托
为了方便开发,系统预定义了两种委托类型:Action委托和Func委托。
Action可以指向没有返回值、没有参数的方法。
csharp
public class App
{
static void printHello()
{
Console.WriteLine("Hello!");
}
static void Main(string[] args)
{
Action a = printHello;
a();
Console.ReadKey();
}
}
Func委托
Func委托可以指向有返回值的方法。
csharp
public class App
{
static int printRes()
{
Console.WriteLine("Hello!");
return -1;
}
static void Main(string[] args)
{
Func<int> a = printRes;
a();
Console.ReadKey();
}
}
匿名方法
csharp
public class App
{
static void Main(string[] args)
{
// 使用Func去创建一个函数类型。最后一个泛型是返回值的类型
// 使用delegate去委托一个方法
Func<int, int, int> plus = delegate(int x, int y) { return x + y; };
Console.WriteLine(plus(1,2));
Console.ReadKey();
}
}