首页 c#委托

c#委托

举报
开通vip

c#委托比如说一个公司(场景),你是老板,手下有两个员工,小张和小王。 你命令小王,如果小张玩游戏,则小王扣去小张500元钱。 这就是现实中的委托。 实际上,在写程序中,程序员就是老板,小张和小王就是两个对象。小张玩游戏是一个方法,小张还有一个游戏事件,他玩游戏激发这个事件。而小王就是事件处理对象,他负责把小张的钱扣除500。 所以,委托有如下几个要素: 1 激发事件的对象--就是小张 2 处理对象事件的对象--就是小王 3 定义委托,就是你让小王监视小张。 如果这三个要素都满足的话,则你就写出了一个完整事...

c#委托
比如说一个公司(场景),你是老板,手下有两个员工,小张和小王。 你命令小王,如果小张玩游戏,则小王扣去小张500元钱。 这就是现实中的委托。 实际上,在写程序中,程序员就是老板,小张和小王就是两个对象。小张玩游戏是一个方法,小张还有一个游戏事件,他玩游戏激发这个事件。而小王就是事件处理对象,他负责把小张的钱扣除500。 所以,委托有如下几个要素: 1 激发事件的对象--就是小张 2 处理对象事件的对象--就是小王 3 定义委托,就是你让小王监视小张。 如果这三个要素都满足的话,则你就写出了一个完整事件的处理。 下面有个例子:在vs.net2003 C#控制台应用程序编辑运行成功: using System; namespace CSharpConsole { public class 场景 { [STAThread] public static void Main(string[] args) { Console.WriteLine("场景开始了...."); // 生成小王 小王 w = new 小王(); // 生成小账 小张 z = new 小张(); // 指定监视 z.PlayGame += new PlayGameHandler(w.扣钱); // 开始玩游戏 z.玩游戏(); console.writeline("场景结束..."); Console.ReadLine(); } } // 负责扣钱的人 public class 小王 { public 小王() { Console.WriteLine("生成小王..."); } public void 扣钱(object sender, EventArgs e) { Console.WriteLine("小王:好小子,上班时间胆敢玩游戏..."); Console.WriteLine("小王:看看你小子有多少钱..."); 小张 f = (小张)sender; Console.WriteLine("小张的钱: " + f.钱.ToString()); Console.WriteLine("开始扣钱......"); System.Threading.Thread.Sleep(500); f.钱 = f.钱 - 500; Console.WriteLine("扣完了....现在小张还剩下:" + f.钱.ToString()); } } // 如果玩游戏,则引发事件 public class 小张 { // 先定义一个事件,这个事件 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 示“小张”在玩游戏。 public event PlayGameHandler PlayGame; // 保存小张钱的变量 private int m_Money; public 小张() { Console.WriteLine("生成小张...."); m_Money = 1000; // 构造函数,初始化小张的钱。 } public int 钱 // 此属性可以操作小张的钱。 { get { return m_Money; } set { m_Money = value; } } public void 玩游戏() { Console.WriteLine("小张开始玩游戏了....."); Console.WriteLine("小张:CS好玩,哈哈哈! 我玩....."); System.Threading.Thread.Sleep(500); System.EventArgs e = new EventArgs(); OnPlayGame(e); } protected virtual void OnPlayGame(EventArgs e) { if (PlayGame != null) { PlayGame(this, e); } } } // 定义委托处理程序 public delegate void PlayGameHandler(object sender, System.EventArgs e); } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C# 委托知识总结 1.什么是委托,为什么要使用委托 我正在埋头苦写程序,突然想喝水,但是又不想自己去掉杯水而打断自己的思路,于是我就想让女朋友去给我倒水。她去给我倒水,首先我得让她知道我想让她干什么,通知她之后我可以继续写自己的程序,而倒水的工作就交给了她。这样的过程就相当于一个委托。 在程序过程中,当程序正在处理某个事件的时候,我需要另外的程序代码去辅助处理一些事情,于是委托另一个程序模块去处理,而委托就可以达到这种目的,我可以利用委托通知另外的程序模块,该去调用哪个函数方法。委托其实就起到了这样一个作用,将函数签名传递到了另一个函数中。或许这样讲还是有些模糊,看看后面的具体实例。 2.委托的定义 delegate int Add(int num1,int num2); delegate void ConvertNum(string result); 上面是定义两个委托的例子,其实很简单。声明一个委托使用delegate关键字,上面分别是定义的带返回值的委托和不带返回值的委托, 两个委托都有传递参数,当然也可以不传递参数。其实委托也是一个类,委托派生为System.MulticastDelegate,而System.MulticastDelegate 又继承System.Delegate,如果你知道这个也就明白委托其实是一个特殊的类。 委托的简单实用例子 1 public delegate string TeaDelegate(string spText); 2 3 public class DelegateSource 4 { 5 public void TestDelegate() 6 { 7 Operator op = new Operator(); 8 TeaDelegate tea = new TeaDelegate(op.GetTea); 9 Console.WriteLine("去给我倒杯水"); 10 Console.WriteLine(); 11 string result=tea("去给我倒杯水"); 12 Thread.Sleep(5000); 13 Console.WriteLine(result); 14 Console.WriteLine(); 15 } 16 } 17 18 public class Operator 19 { 20 /// 21 /// 确定是否还有水 22 /// 23 private bool flag = true; 24 25 public string GetTea(string spText) 26 { 27 if (spText == "去给我倒杯水") 28 { 29 if (flag) 30 { 31 return "老公,茶来了"; 32 } 33 else 34 { 35 return "老公,没有水了"; 36 } 37 } 38 return "等待......."; 39 } 40 } 输出结果 上面使用最普通的一种方式来定义了一个委托的使用,这个例子虽然很简单,但是能够很形象的描述委托的使用。 3.委托的三种形式 (1).推断 推断委托例子 1 public delegate string TeaDelegate(string spText); 2 3 public class DelegateSource 4 { 5 public void TestDelegate() 6 { 7 Operator op = new Operator(); 8 TeaDelegate tea = op.GetTea; 9 Console.WriteLine("去给我倒杯水"); 10 Console.WriteLine(); 11 string result=tea("去给我倒杯水"); 12 Thread.Sleep(5000); 13 Console.WriteLine(result); 14 Console.WriteLine(); 15 } 16 } 17 18 public class Operator 19 { 20 /// 21 /// 确定是否还有水 22 /// 23 private bool flag = true; 24 25 public string GetTea(string spText) 26 { 27 if (spText == "去给我倒杯水") 28 { 29 if (flag) 30 { 31 return "老公,茶来了"; 32 } 33 else 34 { 35 return "老公,没有水了"; 36 } 37 } 38 return "等待......."; 39 } 40 } 在委托定义的例子中我们看到委托的使用方法是在委托实例化的时候指定的[new DelegateName(FunctionName)],这里可能表述不是太但是代码应该看得白了。 而委托的推断,并没有new 委托这个步骤,而是直接将Function 指定给委托。 (2).匿名函数 匿名委托例子 1 public delegate string TeaDelegate(string spText); 2 3 public class DelegateSource 4 { 5 public void TestDelegate() 6 { 7 Operator op = new Operator(); 8 bool flag = true; 9 TeaDelegate tea = delegate(string spText) 10 { 11 if (spText == "去给我倒杯水") 12 { 13 if (flag) 14 { 15 return "老公,茶来了"; 16 } 17 else 18 { 19 return "老公,没有水了"; 20 } 21 } 22 return "等待......."; 23 }; 24 25 Console.WriteLine("去给我倒杯水"); 26 Console.WriteLine(); 27 string result=tea("去给我倒杯水"); 28 Thread.Sleep(5000); 29 Console.WriteLine(result); 30 Console.WriteLine(); 31 } 32 } 至于匿名委托,给人的感觉更为直接了,都不用显示的指定方法名,因为根本没有方法,而是指定的匿名方法。匿名方法在.NET 中提高了 代码的可读性和优雅性。对于更多操作较少的方法直接写为匿名函数,这样会大大提高代码的可读性。这里有两个值得注意的地方: 第一,不能使用 跳转语句跳转到该匿名方法外,第二 不能使用ref,out修饰的参数 (3).多播委托 多播委托例子 1 public delegate string TeaDelegate(string spText); 2 3 public class DelegateSource 4 { 5 public void TestDelegate() 6 { 7 Operator op = new Operator(); 8 9 TeaDelegate tea1 = op.GetTea; 10 TeaDelegate tea2 = op.Speak; 11 TeaDelegate tea = tea1 + tea2; 12 13 Console.WriteLine("去给我倒杯水"); 14 Console.WriteLine(); 15 string result=tea("去给我倒杯水"); 16 Thread.Sleep(5000); 17 Console.WriteLine(result); 18 Console.WriteLine(); 19 } 20 } 21 22 public class Operator 23 { 24 /// 25 /// 确定是否还有水 26 /// 27 private bool flag = true; 28 29 public string GetTea(string spText) 30 { 31 if (spText == "去给我倒杯水") 32 { 33 if (flag) 34 { 35 return "老公,茶来了"; 36 } 37 else 38 { 39 return "老公,没有水了"; 40 } 41 } 42 return "等待......."; 43 } 44 45 46 public string Speak(string spText) 47 { 48 Console.WriteLine("\n去把我的设计图稿拿来"); 49 return null; 50 } 51 } 还是上面的那个实例,我不尽想让女朋友去给我掉杯水,还让她帮我将程序设计图稿拿过来。这个时候做的就不是一件事了,而是多件。 程序中也有很多这种情况,于是我们需要多播委托,在一个委托上指定多个执行方法,这是在程序中可以行的。上面提到了,委托直接继承于 System.MulticastDelegate,正是因为这个类可以实现多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名就必须返回void;否则,就只能得到委托调用的最后一个方法的结果。所以在上面的这段代码中是得不到结果的 4.事件 使用C#编程,无论是WinForm,WebForm 给人很难忘得就是它的控件,而他们的控件库使用方式都是使用使用事件驱动模式,而事件驱动模式却少不了委托。话不多说,看代码能够更清好的理解事件和委托之间的联系. 事件的使用 1 public delegate void MyDelegate(string name); 2 3 public class EventSource 4 { 5 public event MyDelegate Event_Delegate; 6 7 public void SetCustomer(string name) 8 { 9 Console.WriteLine("事件发生.....\n"); 10 Console.WriteLine("hi! "+name); 11 } 12 13 public void TestEvent() 14 { 15 EventSource source = new EventSource(); 16 Console.WriteLine("订阅事件.....\n"); 17 source.Event_Delegate += new MyDelegate(source.SetCustomer); 18 Console.WriteLine("触发事件.....\n"); 19 source.Event_Delegate("hechen"); 20 Console.WriteLine(".................."); 21 } 22 } 上面的代码中我们定义了一个委托,然后定义了一个类EventSource,这个类中声明了一个事件。定义一个事件使用event 关键字,定义一 个event必须指定这个event传递消息的委托,在触发事件之前必需订阅事件,我们使用+= new 语法来订阅一个事件,也就相当于实例化一个事件。 当我们触发事件的时候,就会调用相应的方法去处理。 5. 泛型委托 委托是类型安全的引用,泛型委托就和我们常用的泛型类一样,这个类在使用的时候才能确定类型.通过泛型委托,我们可以在委托传递参数 之后知道它的类型.在.NET中有一个很典型的泛型委托: public delegate voie EventHandler(object sender,TEventArgs e) where TEventArgs:EventArgs. 这是一个非常有特色的泛型委托,可能我们用的比较少,但是作用是不能忽视的。 我们看看三个非常具有代表性的泛型委托.现在.NET4.0已经出来了,但是泛型委托.NET2.0就出来了,Linq 大家用的那叫一个甜, 为啥 函数式编程风格,匿名方法,Lamda表达式表达式使用是如此的魅力。但是大家仔细观察过没有,Linq 中的方法有几个经常出现的参数: Action,Predicate,Func Func:封装一个具有一个参数并返回 E 参数指定的类型值的方法,T 是这个委托封装方法的参数类型,E是方法的返回值类型。当然Func 只是其中的一种情况,这个委托还有其他的几种情况:Func 这个是方法没有参数,返回值类型是T;Func 这个方法有两个参数,类型分别为T1,T2,返回值是Result,还有Func,Func 这几中情况,具体情况就不介绍了.我们还可以通过扩展类型,扩展为更多的参数. Func 委托的使用 1 public void TestFunc() 2 { 3 TEventSource eventSource=new TEventSource(); 4 Func func = eventSource.GetTea; 5 string result = func("茶"); 6 Console.WriteLine(result); 7 } 8 9 public string GetTea(string context) 10 { 11 if (context == "茶") 12 { 13 return "茶来了"; 14 } 15 else 16 { 17 return "设计稿子来了"; 18 } 19 } Action:封装一个方法,该方法只采用一个参数并且不返回值,包括Action,Action,Action,Action 这几种情况,也可以通过扩展方法去扩展参数的个数 。 Action 委托使用例子 1 public void TestAction() 2 { 3 TEventSource eventSource = new TEventSource(); 4 Action action = eventSource.Speak; 5 action("Action 泛型委托"); 6 } 7 8 public void Speak(string context) 9 { 10 Console.WriteLine(context); 11 } Predicate:表示定义一组条件并确定指定对象是否符合这些条件的方法。该委托返回的是一个bool类型的值,如果比较满足条件 返回true,否则返回false.其实上面的Func 委托可以包含这个委托.不过这个委托和上面的两个不一样,它只有一种类型 Predicate 委托使用例子 1 public void TestPredicate() 2 { 3 TEventSource eventSource = new TEventSource(); 4 Predicate predicate = eventSource.IsRigth; 5 Console.WriteLine(predicate(0)); 6 } 7 8 public bool IsRigth(int value) 9 { 10 if (value == 0) 11 { 12 return true; 13 } 14 else 15 { 16 return false; 17 } 18 } 6.异步委托 投票技术: 委托其实相当于一个线程,使用投票技术是使用异步委托的一种实现方式.Delegate类提供了方法BeginInvoke(),可以传送委托类型定义的输入参数,其返回类型为IAsyncResult。IAsyncResult的IsCompleted属性可以判断委托任务是否完成 异步委托投票技术 1 public delegate int DelegateVote(int data, int ms); 2 /// 3 /// 使用投票操作完成委托任务 4 /// 5 public class VoteDelegate 6 { 7 /// 8 /// 休眠特定时间执行操作 9 /// 10 /// 11 /// 12 /// 13 public static int TakeWork(int data, int ms) 14 { 15 Console.WriteLine("开始调用TakeWork方法"); 16 Thread.Sleep(ms); 17 Console.WriteLine("结束调用TakeWork方法"); 18 return data + 10; 19 } 20 21 public void TestDelegate() 22 { 23 DelegateVote voteDel = TakeWork; 24 IAsyncResult result = voteDel.BeginInvoke(1,5000,null,null); 25 while (result.IsCompleted == false) 26 { 27 Console.WriteLine("等待......"); 28 Thread.Sleep(500); 29 } 30 int value = voteDel.EndInvoke(result); 31 Console.WriteLine("委托调用结果: "+value); 32 } 33 } 等待句柄:等待句柄是使用AsyncWaitHandle属性访问,返回一个WaitHandle类型的对象,它可以等待委托线程完成其任务。在这个参数中可以设置最大的等待时间。 异步委托等待句柄 1 public delegate string WaitDelegate(string content); 2 3 public class WaitHandlerDelegate 4 { 5 public void TestWaitHander() 6 { 7 WaitDelegate del = GetTea; 8 IAsyncResult ar = del.BeginInvoke("hechen", null, null); 9 while (true) 10 { 11 Console.Write("."); 12 if (ar.AsyncWaitHandle.WaitOne(50, false)) 13 { 14 break; 15 } 16 } 17 string result=del.EndInvoke(ar); 18 Console.WriteLine(result); 19 20 } 21 22 public static string GetTea(string content) 23 { 24 return "茶来了 "+content; 25 } 26 } 异步回调:这个方式和投票技术有点类似,不过在投票方式中BeginInvoke()方法第三个参数指定了一个方法签名,而这个方法参数接收IAsyncResult 类型的参数。 异步委托回调函数 1 public delegate string AsyDelegate(string content); 2 3 public class AsyncresultDelegate 4 { 5 public void TestAsync() 6 { 7 AsyDelegate del = GetTea; 8 del.BeginInvoke("hechen", delegate(IAsyncResult ar) { 9 Thread.Sleep(5000); 10 string result = del.EndInvoke(ar); 11 Console.WriteLine(result); 12 }, null); 13 for (int i = 0; i < 100; i++) 14 { 15 Console.WriteLine("等待....."); 16 Thread.Sleep(1000); 17 } 18 } 19 20 public static string GetTea(string content) 21 { 22 return "茶来了 " + content; 23 } 24 }
本文档为【c#委托】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_043105
暂无简介~
格式:doc
大小:89KB
软件:Word
页数:21
分类:互联网
上传时间:2013-12-02
浏览量:25