委托
简单记录点东西 适合似懂非懂的朋友看看
委托类型用来定义和响应应用程序中的回调
借此可以设计各种有面向对象特性的代码模式下面要说的事件在我看来就是委托的一种实现, 再深一步讲, 利用委托加事件, 是不是可以构建各种所谓的管道框架
如 ASP.NET webAPI 的管道模型, 整个消息处理管道是通过一组有序的 HttpMessagHandler 首尾相连而成, 具体实现串联的是通过 DelegatingHandler 这个类型来完成的即是一组委托链
最精华的内容您已看完
委托定义 public delegate int DeleName(int x);
名称
参数
返回值
1 委托简单示例
- DeleName del = M1;
- public int M1(int i)
- {
- ...
- }
入门理解 1: 委托是方法的类型, 即委托 = class, 方法 = new class()
上面的方法名称 M1 只起到传递作用时, 可以用匿名委托代替:
- DeleName del = delegate (int i)
- {
- ...
- };
除了用匿名委托, 还可以用 lamda 表达式进行代替:
- DeleName del = (int i)=>
- {
- ...
- };
在这里也能看出 lamda 本质就是委托
2 泛型委托
- public delegate void MyGenericDelegate1<T>(T arg);
- public delegate int MyGenericDelegate2<T,M>(T arg,M name);
- MyGenericDelegate1<int> intTarget = new MyGenericDelegate<int>(IntTarget);
- static void IntTarget(int arg) => Console.WriteLine($"IntTarget--> {++arg}");
- MyGenericDelegate2<int,string> intTarget1 = (int arg,string name) =>
- {
- return 1;
- };
好处: 封装为了复用
看下上面两个委托的命名: MyGenericDelegate1 MyGenericDelegate2 纯粹为了取名而取名, 此时我们可以不自己取名
怎么做呢, C# 本身提供了两个泛型委托可以给我们使用, 且可满足大多数场景
3 泛型 Action<> 和 Func<> 委托
(可指向至多传递 16 个参数的方法)
Action<>: 无返回值: 定义 public delegate void Action<...>
- public static void Show() {
- // 使用 Action<>委托来指向 DisplayMessage()
- Action < string,
- ConsoleColor,
- int > actionTarget = new Action < string,
- ConsoleColor,
- int > (DisplayMessage);
- actionTarget("actionTarget", ConsoleColor.Red, 5);
- }
- // Action<> 委托的一个目标
- private static void DisplayMessage(string msg, ConsoleColor txtColor, int printCount) {...
- }
Func<>: 有返回值 public delegate TResult Func<..., out TResult> TResult: 返回值类型
- Func<int, int, int> funcTarget = new Func<int, int, int>(Add);
- funcTarget(1, 2);
- static int Add(int x, int y) => x + y;
如果你觉得一个具有自定义名称的委托更有助于捕获问题范畴, 那么构建自定义委托不过就是一行代码的事儿
注: Linq 中就大量的用到了 Action<> 和 Func<>
4 事件
最简单的说法是: 可以把事件看成是委托的一个实例委托比作类: 它定义了函数的签名 (接受什么类型的参数 返回什么类型的值) 事件比作委托 new 出来的一个实例, 是具有该委托签名的具体函数当然事件和实例也是有区别的:
1 事件这个东西 能容纳很多个具体的函数(通过 += -= 增加删除)
2 事件有 event 关键字起到了保护作用不允许改变事件的引用即在声明事件的类外部不能用 = 对事件对象赋值
直接看看代码
- public delegate void HelloWorldDelegate(string name);
- public class HelloWorldClass2
- {
- public event HelloWorldDelegate del;//!!!!event 修饰了委托对象
- public void HelloWorld(string name)
- {
- //del = (n) => { Console.WriteLine(n); };// 在声明事件的类内部可以用 = 直接定义事件的引用(赋值)
- del(name);
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- HelloWorldClass2 h2 = new HelloWorldClass2();
- //h2.del = ByEnglish;// 不允许改变事件的引用(不能用 = 赋值)
- h2.del += ByEnglish;// 第一种
- // 手工创建一个委托变量是最直接的方式但是大多数情况下, 我们并不依靠委托对象我们可以使用 C# 提供的方法组转换的方法, 它允许我们在调用以委托作为参数的方法时直接提供了与委托期望的签名想匹配的方法的名称(返回 void, 参数 string), 而不是创建委托对象(所以一般直接用上面这种)
- HelloWorldDelegate de = ByChinese;
- h2.del += de;// 第二种
- h2.HelloWorld("mary");
- Console.ReadLine();
- }
- static void ByEnglish(string name)
- {
- Console.WriteLine("hello,world"+name);
- }
- static void ByChinese(string name)
- {
- Console.WriteLine("你好, 世界" + name);
- }
- }
事件默认是个多播委托, 什么是多播委托呢? 就是上面的 h2.del 委托容纳的方法有多个, ByEnglish 跟 ByChinese, 用 += 可以继续往下延伸
委托和事件的区别在于, 事件是个规约, 委托是个实现(当然抽象上的委托也可以不是个具体的实现)
规约的含义是, 我定义了这么个语法, 你可以通过 += 和 -= 把委托挂载到这个东西 (事件) 上, 当发生这个事件的时候, 我会确保这些委托都被得到调用但是具体是怎么调用的, 你不用关心
欢迎讨论~
来源: https://www.cnblogs.com/joeymary/p/8486358.html