C# 委托知识总结

1.什么是委托,为什么要使用委托

我正在埋头苦写程序,突然想喝水,但是又不想自己去掉杯水而打断自己的思路,于是我就想让女朋友去给我倒水。她去给我倒水,首先我得让她知道我想让她干什么,通知她之后我可以继续写自己的程序,而倒水的工作就交给了她。这样的过程就相当于一个委托。

在程序过程中,当程序正在处理某个事件的时候,我需要另外的程序代码去辅助处理一些事情,于是委托另一个程序模块去处理,而委托就可以达到这种目的,我可以利用委托通知另外的程序模块,该去调用哪个函数方法。委托其实就起到了这样一个作用,将函数签名传递到了另一个函数中。或许这样讲还是有些模糊,看看后面的具体实例。

 

2.委托的定义

delegate int Add(int num1,int num2);

delegate void ConvertNum(string result);

上面是定义两个委托的例子,其实很简单。声明一个委托使用delegate关键字,上面分别是定义的带返回值的委托和不带返回值的委托, 

两个委托都有传递参数,当然也可以不传递参数。其实委托也是一个类,委托派生为System.MulticastDelegate,而System.MulticastDelegate

又继承System.Delegate,如果你知道这个也就明白委托其实是一个特殊的类。

 

委托的简单实用例子Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public delegate string TeaDelegate(string spText);public class DelegateSource{public void TestDelegate(){Operator op = new Operator();TeaDelegate tea = new TeaDelegate(op.GetTea);Console.WriteLine("去给我倒杯水");Console.WriteLine();string result=tea("去给我倒杯水");Thread.Sleep(5000);Console.WriteLine(result);Console.WriteLine();}}public class Operator{/// <summary>/// 确定是否还有水/// </summary>private bool flag = true;public string GetTea(string spText){if (spText == "去给我倒杯水"){if (flag){return "老公,茶来了";}else{return "老公,没有水了";}}return "等待.......";}}
View Code

输出结果

 

上面使用最普通的一种方式来定义了一个委托的使用,这个例子虽然很简单,但是能够很形象的描述委托的使用。

3.委托的三种形式

(1).推断

推断委托例子Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public delegate string TeaDelegate(string spText);public class DelegateSource{public void TestDelegate(){Operator op = new Operator();TeaDelegate tea = op.GetTea;Console.WriteLine("去给我倒杯水");Console.WriteLine();string result=tea("去给我倒杯水");Thread.Sleep(5000);Console.WriteLine(result);Console.WriteLine();}}public class Operator{/// <summary>/// 确定是否还有水/// </summary>private bool flag = true;public string GetTea(string spText){if (spText == "去给我倒杯水"){if (flag){return "老公,茶来了";}else{return "老公,没有水了";}}return "等待.......";}}
View Code

在委托定义的例子中我们看到委托的使用方法是在委托实例化的时候指定的[new DelegateName(FunctionName)],这里可能表述不是太但是代码应该看得白了。 而委托的推断,并没有new 委托这个步骤,而是直接将Function 指定给委托。

 (2).匿名函数

匿名委托例子Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public delegate string TeaDelegate(string spText);public class DelegateSource{public void TestDelegate(){Operator op = new Operator();bool flag = true;TeaDelegate tea = delegate(string spText){if (spText == "去给我倒杯水"){if (flag){return "老公,茶来了";}else{return "老公,没有水了";}}return "等待.......";};Console.WriteLine("去给我倒杯水");Console.WriteLine();string result=tea("去给我倒杯水");Thread.Sleep(5000);Console.WriteLine(result);Console.WriteLine();}}
View Code

至于匿名委托,给人的感觉更为直接了,都不用显示的指定方法名,因为根本没有方法,而是指定的匿名方法。匿名方法在.NET 中提高了 

代码的可读性和优雅性。对于更多操作较少的方法直接写为匿名函数,这样会大大提高代码的可读性。这里有两个值得注意的地方: 第一,不能使用

跳转语句跳转到该匿名方法外,第二 不能使用ref,out修饰的参数

(3).多播委托

多播委托例子Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public delegate string TeaDelegate(string spText);public class DelegateSource{public void TestDelegate(){Operator op = new Operator();TeaDelegate tea1 = op.GetTea;TeaDelegate tea2 = op.Speak;TeaDelegate tea = tea1 + tea2;Console.WriteLine("去给我倒杯水");Console.WriteLine();string result=tea("去给我倒杯水");Thread.Sleep(5000);Console.WriteLine(result);Console.WriteLine();}}public class Operator{/// <summary>/// 确定是否还有水/// </summary>private bool flag = true;public string GetTea(string spText){if (spText == "去给我倒杯水"){if (flag){return "老公,茶来了";}else{return "老公,没有水了";}}return "等待.......";}public string Speak(string spText){Console.WriteLine("\n去把我的设计图稿拿来");return null;}}
View Code

还是上面的那个实例,我不尽想让女朋友去给我掉杯水,还让她帮我将程序设计图稿拿过来。这个时候做的就不是一件事了,而是多件。

程序中也有很多这种情况,于是我们需要多播委托,在一个委托上指定多个执行方法,这是在程序中可以行的。上面提到了,委托直接继承于

System.MulticastDelegate,正是因为这个类可以实现多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名就必须返回void;否则,就只能得到委托调用的最后一个方法的结果。所以在上面的这段代码中是得不到结果的

 

4.事件

使用C#编程,无论是WinForm,WebForm 给人很难忘得就是它的控件,而他们的控件库使用方式都是使用使用事件驱动模式,而事件驱动模式却少不了委托。话不多说,看代码能够更清好的理解事件和委托之间的联系. 

事件的使用Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public delegate void MyDelegate(string name);public class EventSource{public event MyDelegate Event_Delegate;public void SetCustomer(string name){Console.WriteLine("事件发生.....\n");Console.WriteLine("hi! "+name);}public void TestEvent(){EventSource source = new EventSource();Console.WriteLine("订阅事件.....\n");source.Event_Delegate += new MyDelegate(source.SetCustomer);Console.WriteLine("触发事件.....\n");source.Event_Delegate("hechen");Console.WriteLine("..................");}}
View Code

上面的代码中我们定义了一个委托,然后定义了一个类EventSource,这个类中声明了一个事件。定义一个事件使用event 关键字,定义一

个event必须指定这个event传递消息的委托,在触发事件之前必需订阅事件,我们使用+= new 语法来订阅一个事件,也就相当于实例化一个事件。

当我们触发事件的时候,就会调用相应的方法去处理。

 

5. 泛型委托

委托是类型安全的引用,泛型委托就和我们常用的泛型类一样,这个类在使用的时候才能确定类型.通过泛型委托,我们可以在委托传递参数

之后知道它的类型.在.NET中有一个很典型的泛型委托:

public delegate voie EventHandler<TEventArgs>(object sender,TEventArgs e) where TEventArgs:EventArgs.

这是一个非常有特色的泛型委托,可能我们用的比较少,但是作用是不能忽视的。 我们看看三个非常具有代表性的泛型委托.现在.NET4.0已经出来了,但是泛型委托.NET2.0就出来了,Linq 大家用的那叫一个甜,

为啥 函数式编程风格,匿名方法,Lamda表达式表达式使用是如此的魅力。但是大家仔细观察过没有,Linq 中的方法有几个经常出现的参数:

Action<T>,Predicate<T>,Func<T, Result>

 Func<T, E>:封装一个具有一个参数并返回 E 参数指定的类型值的方法,T 是这个委托封装方法的参数类型,E是方法的返回值类型。当然Func<T, Result> 只是其中的一种情况,这个委托还有其他的几种情况:Func<T> 这个是方法没有参数,返回值类型是T;Func<T1,T2,Result> 这个方法有两个参数,类型分别为T1,T2,返回值是Result,还有Func<T1,T2,T3,Result>,Func<T1,T2,T3,T4,Result> 这几中情况,具体情况就不介绍了.我们还可以通过扩展类型,扩展为更多的参数.

Func 委托的使用Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public void TestFunc()
        { TEventSource eventSource=new TEventSource();Func<string, string> func = eventSource.GetTea;string result = func("");Console.WriteLine(result);}public string GetTea(string context){if (context == ""){return "茶来了";}else{return "设计稿子来了";}}
View Code

Action<T>:封装一个方法,该方法只采用一个参数并且不返回值,包括Action<T>,Action<T1,T2>,Action<T1,T2,T3>,Action<T1,T2,T3,T4> 这几种情况,也可以通过扩展方法去扩展参数的个数 。

Action 委托使用例子Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public void TestAction()
        {TEventSource eventSource = new TEventSource();Action<string> action = eventSource.Speak;action("Action<T> 泛型委托");}public void Speak(string context){Console.WriteLine(context);}
Action 委托使用例子

Predicate<T>:表示定义一组条件并确定指定对象是否符合这些条件的方法。该委托返回的是一个bool类型的值,如果比较满足条件 

返回true,否则返回false.其实上面的Func 委托可以包含这个委托.不过这个委托和上面的两个不一样,它只有一种类型

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public void TestPredicate()
        {TEventSource eventSource = new TEventSource();Predicate<int> predicate = eventSource.IsRigth;Console.WriteLine(predicate(0));}public bool IsRigth(int value){if (value == 0){return true;}else{return false;}}
Predicate 委托使用例子

6.异步委托

投票技术: 委托其实相当于一个线程,使用投票技术是使用异步委托的一种实现方式.Delegate类提供了方法BeginInvoke(),可以传送委托类型定义的输入参数,其返回类型为IAsyncResult。IAsyncResult的IsCompleted属性可以判断委托任务是否完成

/// <summary>/// 使用投票操作完成委托任务/// </summary>public class VoteDelegate{/// <summary>/// 休眠特定时间执行操作/// </summary>/// <param name="data"></param>/// <param name="ms"></param>/// <returns></returns>public static int TakeWork(int data, int ms){Console.WriteLine("开始调用TakeWork方法");Thread.Sleep(ms);Console.WriteLine("结束调用TakeWork方法");return data + 10;}public void TestDelegate(){DelegateVote voteDel = TakeWork;IAsyncResult result = voteDel.BeginInvoke(1,5000,null,null);while (result.IsCompleted == false){Console.WriteLine("等待......");Thread.Sleep(500);}int value = voteDel.EndInvoke(result);Console.WriteLine("委托调用结果:  "+value);}}
异步委托投票技术

 

等待句柄:等待句柄是使用AsyncWaitHandle属性访问,返回一个WaitHandle类型的对象,它可以等待委托线程完成其任务。在这个参数中可以设置最大的等待时间。

  public delegate string WaitDelegate(string content);public class WaitHandlerDelegate{public void TestWaitHander(){WaitDelegate del = GetTea;IAsyncResult ar = del.BeginInvoke("hechen", null, null);while (true){Console.Write(".");if (ar.AsyncWaitHandle.WaitOne(50, false)){break;}}string result=del.EndInvoke(ar);Console.WriteLine(result);}public static string GetTea(string content){return "茶来了  "+content;}}
异步委托等待句柄

异步回调:这个方式和投票技术有点类似,不过在投票方式中BeginInvoke()方法第三个参数指定了一个方法签名,而这个方法参数接收IAsyncResult 类型的参数。

 public class AsyncresultDelegate{public void TestAsync(){AsyDelegate del = GetTea;del.BeginInvoke("hechen", delegate(IAsyncResult ar) {Thread.Sleep(5000);string result = del.EndInvoke(ar);Console.WriteLine(result);}, null);for (int i = 0; i < 100; i++){Console.WriteLine("等待.....");Thread.Sleep(1000);}}public static string GetTea(string content){return "茶来了  " + content;}}
异步委托回调函数

 

转载于:https://www.cnblogs.com/12xiaole/p/8289169.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/281383.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里云大学课程学习有奖征文活动现在开始

2019独角兽企业重金招聘Python工程师标准>>> "学有所获&#xff0c;分享为美"--阿里云大学课程学习有奖征文活动开始啦~~ 看课程&#xff0c;写心得&#xff0c;赢千元大奖&#xff0c;还有机会加入阿里云大学技术作者群&#xff01;想试试自己的技术文笔…

Android 的系统架构

Android 的系统架构和其它操作系统一样&#xff0c;采用了分层的架构。android 分为四个层&#xff0c;从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和 linux 核心层。 Android 是以 Linux 为核心的手机操作平台&#xff0c;作为一款开放式的操作系统&#xf…

记一次 .NET 某制造业 MES 系统崩溃分析

一&#xff1a;背景 1.讲故事前段时间有位朋友微信找到我&#xff0c;说他的程序偶尔会出现内存溢出崩溃&#xff0c;让我帮忙看下是怎么回事&#xff0c;咨询了下程序是 x86 部署&#xff0c;听到这个词其实心里已经有了数&#xff0c;不管怎么样还是用 windbg 分析一下。二&a…

首次公开!单日600PB的计算力--阿里巴巴EB级大数据平台的进击

摘要&#xff1a; 每年的双11之前&#xff0c;也是MaxCompute各种乾坤大挪移落定的时候&#xff0c;因为双11就是各种大折腾项目的自然deadline。在今年双11之前&#xff0c;一路向北迁移和在离线混部项目&#xff0c;将杭州集群除蚂蚁外整体迁移到张北&#xff0c;涉及了绝大部…

软件测试金字塔

软件测试金字塔 在敏捷方法中&#xff0c;持续集成是其基石&#xff0c;持续集成的核心是自动化测试。下面这篇关于测试金字塔的文章&#xff0c;来自大师Martin Fowler。 测试金字塔的概念来自Mike Cohn&#xff0c;在他的书Succeeding With Agile中有详细描述&#xff1a;测试…

使用pm2守护你的.NET Core应用程序

简介PM2是常用的node进程管理工具&#xff0c;它可以提供node.js应用管理&#xff0c;如自动重载、性能监控、负载均衡等。同类工具有Supervisor、Forever等。pm2是一个进程管理工具,可以用它来管理你的node进程&#xff0c;并查看node进程的状态&#xff0c;当然也支持性能监控…

程序员搞笑段子

转载于:https://www.cnblogs.com/Zhusi/p/10083474.html

CA周记 - 在 Azure ML 上用 .NET 跑机器学习

.NET 是一个跨平台&#xff0c;全场景应用的开源技术。你有在用 .NET 做机器学习/深度学习的应用吗&#xff1f;如果从框架角度&#xff0c;ML.NET / Tensorflow.NET / 不断在进步的 TorchSharp 通过几年的发展已经开始稳定&#xff0c;但如果在一些大型项目上&#xff0c;特别…

iOS10 优化APP首次安装网络权限提示方案

我刚经历了一场末日&#xff08;停电&#xff09;&#xff0c;特别是在你想写文档的时候。。。 言归正传&#xff0c;今天的问题是解决iOS10系统下首次按钮APP弹出的网络权限提示所带来了问题以及优化。 起因 查了相关文章知道由于大陆工信部出台的新规指出&#xff0c;应用在未…

su命令

从一个用户切换到另一个用户&#xff1a;su - ceshi(ceshi是用户名) 查看当前用户&#xff1a;whoami 在不切换用户的情况执行另一个用户的命令&#xff1a;例&#xff1a;su - -c "touch /tmp/111.txt" admin 若用户没有加目录需要添加家目录&#xff0c;并更改所有…

PS批量替换内容

在制作图片物料的时候&#xff0c;有时会碰到需要制作大量内容格式一致&#xff0c;但部分文字或图片不同的图片&#xff0c;这里我们使用PS的变量功能 物料准备&#xff1a;准备好需要替换的图片和文字&#xff0c;使用excel制作出需要替换的内容&#xff0c;第一行name和pic…

在 .NET 中执行 JavaScript 代码

你好&#xff0c;这里是 Dotnet 工具箱&#xff0c;定期分享 Dotnet 有趣&#xff0c;实用的工具和组件&#xff0c;希望对您有用&#xff01;Jint 简介如果您想在您的 .NET 程序中使用 Javascript&#xff0c;那么我推荐您使用 Jint。Jint 是适用于 .NET 的 开源 Javascript 解…

jmeter多用户登录跨线程组操作传值

项目需求&#xff1a; 需要登录两个用户A、B&#xff0c;用户A操作完后会通知B&#xff0c;然后B再操作&#xff0c;B操作完结束或者再通知A。 实现思路&#xff1a; 1. 设置两个线程组Ⅰ、Ⅱ&#xff0c;组Ⅰ添加cookie管理器&#xff0c;里面添加用户A的操作&#xff1b;组Ⅱ…

手动修改美化7zip图标 - 附替换文件

手动修改7zip图标理论知识制作ico图标文件替换资源重建图标缓存效果图替换文件7-Zip的自带图标是公认的丑&#xff0c;所以网上有很多7-Zip的图标美化工具&#xff0c;用的最多的就是 7-Zip Theme Manager&#xff0c;自带很多主题&#xff0c;但是最近我再使用7zTM修改图标是却…

.NET性能优化-复用StringBuilder

在之前的文章中&#xff0c;我们介绍了 dotnet 在字符串拼接时可以使用的一些性能优化技巧。比如&#xff1a;为StringBuilder设置 Buffer 初始大小使用ValueStringBuilder等等 不过这些都多多少少有一些局限性&#xff0c;比如StringBuilder还是会存在new StringBuilder()这样…

如何使用vue组件搭建网页并打包发布

vue组件化项目搭建及编译打包发布引言开发环境开发环境介绍开发环境安装使用模板创建项目编译及打包发布引言 最近开始学习Vue&#xff0c;Vue 是一个前端框架&#xff0c;特点是数据绑定和组件化。网上很多教程&#xff0c;数据绑定和组件学习起来也都不困难&#xff0c;但是…

Facebook揭秘其应用测试平台,并开源核心技术

本周&#xff0c;Facebook让一群记者参观了它位于俄勒冈州普赖恩维尔市的数据中心&#xff0c;在这个过程中也展示了他们的一个移动应用测试实验室&#xff0c;用来测试Facebook app、 Messenger 和Instagram。 目前 这个实验室总共含有60个机架&#xff0c;每个机架上放置32台…

责任链模式 职责链模式 Chain of Responsibility Pattern 行为型 设计模式(十七)

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;职责链模式意图 使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接受者之间的耦合关系将这些对象连接成一条链&#xff0c;并沿着这条链传递请求&#xff0c;直到有一个对象处理它为止。责任…

YOLOv7 在 ML.NET 中使用 ONNX 检测对象

本文介绍如何在 ML.NET 中使用 YOLOv7 的 ONNX 模型来检测图像中的对象。什么是 YOLOYOLO&#xff08;You Only Look Once&#xff09;是一种先进的实时目标检测系统。它是一个在COCO数据集上预训练的物体检测架构和模型系列&#xff0c;其版本也是在不断优化更新。2022年7月&a…

NppFTP小插件的使用

大家在Linux系统中配置运行环境时&#xff0c;一定会遇到相关配置文件的修改&#xff0c;虽说在Linux系统中可以使用vi,vim的命令进行文本编辑&#xff0c;但是操作起来还是没有在Windows系统中用的爽&#xff0c;特别是操作大文本量的文件时。Notepad里提供了一个小插件&#…