理解C#委托(Delegate)通俗易懂,深入浅出
理解C#委托(Delegate)通俗易懂,深入浅出
委托是什么?
委托首先是一个数据类型,我们可以像定义结构体一样定义一个委托类型,委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变
委托的定义
//语法
delegate <return type> <delegate-name> <parameter list>
//实例
public delegate int MyDelegate (string s);
实例化委托(Delegate)
例如:
public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);
说白了就是类似指向函数方法的指针,我们可以类似定义指针类型一样,定义委托的类型
在定义委托类型时要指定函数的参数类型和返回值,一旦声明了委托类型,委托对象必须使用 new 关键字来创建,且与一个特定的方法有关。当创建委托时,传递到 new 语句的参数就像方法调用一样书写,但是不带有参数。
简单用法实例
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();
}
}
}
这只是简单的用法介绍,可以看出 这和在主程序里直接调用方法没啥区别,并不是实际的用法。
委托的用途
多播
委托对象可使用 “+” 运算符进行合并。一个合并委托调用它所合并的两个委托。只有相同类型的委托可被合并。"-" 运算符可用于从合并的委托中移除组件委托。
使用委托的这个有用的特点,您可以创建一个委托被调用时要调用的方法的调用列表。这被称为委托的 多播(multicasting),也叫组播。下面的程序演示了委托的多播
static void Main(string[] args)
{
// 创建委托实例
NumberChanger nc;
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
nc = nc1;
nc += nc2;
// 调用多播
nc(5);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}
关键: 委托的使用场景
委托,故名思意,咱们用一个形象的比喻,公司里 ,老板/调用者 ,可以不用委托我/激活委托函数,亲自去给张三/func1,李四/func2 安排工作,就是直接调用,这时或许要准备调用的参数和调用方式的代码 比如循环调用,
老板/调用者 还可以通过我/激活委托的函数 去安排张三李四的工作,同时也可以指定张三/func1,李四/func2 一起工作/±多播,也可以拓展新的员工/方法。
和类的继承多态有异曲同工之妙,不过更加灵活,我/激活委托函数 不需要知道自己要调用什么函数以及具体实现,只管用调用者给的参数就行了 ,父类不用管子类如何实现的,通过子类型的赋值,就能调用子类重写的方法。
//委托
// 委托声明
public delegate void doSomething(string s);
//定义 回调函数 ,公司里的员工 张三,李四.............
public static void ZangSan(string a) {
Console.WriteLine("zhangsan"+a);
}
public static void LiSi(string a)
{
Console.WriteLine("lisi"+a);
}
/// <summary>
/// 中介,委托处理 ,使用此方法触发委托回调
/// </summary>
/// <param name="from">开始</param>
/// <param name="to">结束</param>
/// <param name="fb">委托引用</param>
private static void handleDelegate(int from, int to, doSomething ds)
{
//一些预处理 ,这样使用委托就比直接调用方便了
for (int val = from; val <= to; val++)
{
if (ds != null)
{
ds(val.ToString());
}
//ds?.Invoke(val); 简化版本调用
}
}
//主函数,调用者 老板
public void testDelegate()
{ //老板通过我/中介 给张三安排工作,
doSomething dsZhangSan = new doSomething(ZangSan);
//给张三李四 按顺序安排工作 //按序执行
doSomething dsLisi = new doSomething(LiSi);
doSomething ds = dsZhangSan + dsLisi;
//在调用的时可以给张三,李四传参数,这里在handleDelegate里面给了 ds(val.ToString());
handleDelegate(0, 3, ds);
//方法的返回值,参数必须完全一样,符合委托类型的定义
}
执行结构
回调函数的机制
把我想象成是独立的提供服务的中介,而老板/函数实现的一方, 张三/func1,李四/func2 ~~~是一个公司的,合作时,老板指定张三或是李四… , 而我不需要关心,我只是在特点条件发生时去调用张三李四就行了
⑴定义一个回调函数;
⑵提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
⑶当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
更多推荐
所有评论(0)