理解C#委托(Delegate)通俗易懂,深入浅出

发布:admin2025-06-07 13:36:10 684条浏览分类:世界杯日本爆冷

理解C#委托(Delegate)通俗易懂,深入浅出

委托是什么?实例化委托(Delegate)说白了就是类似指向函数方法的指针,我们可以类似定义指针类型一样,定义委托的类型简单用法实例委托的用途多播关键: 委托的使用场景执行结构回调函数的机制

委托是什么?

委托首先是一个数据类型,我们可以像定义结构体一样定义一个委托类型,委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变

委托的定义

//语法

delegate

//实例

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);

}

///

/// 中介,委托处理 ,使用此方法触发委托回调

///

/// 开始

/// 结束

/// 委托引用

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 ~~~是一个公司的,合作时,老板指定张三或是李四… , 而我不需要关心,我只是在特点条件发生时去调用张三李四就行了

⑴定义一个回调函数;

⑵提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;

⑶当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。