我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C#开发中事件与委托机制的示例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C#开发中事件与委托机制的示例分析

这篇文章给大家分享的是有关C#开发中事件与委托机制的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

概述

C#中的委托类似于C或C++中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象,而且是类型安全的。

C#中的“事件”是当对象发生某些事情时,类向该类的客户提供通知的一种方法。事件最常见的用途是用于图形用户界面;通常,表示界面中的控件的类具有一些事件,当用户对控件进行某些操作(如单击某个按钮)时,将通知这些事件。

使用委托来声明事件。委托对象封装一个方法,以便可以匿名调用该方法。事件是类允许客户为其提供方法(事件发生时应调用这些方法)的委托的一种方法。事件发生时,将调用其客户提供给它的委托。

注明:委托是对方法的包装 在不确定要调用什么方法时候而又不能用抽象或者多态实现的时候用委托。

public interface PilotLamp     {    /// <summary>    /// green light    /// </summary>    void TurnOn();     /// <summary>     /// notice     /// </summary>     string Notice     {     get;    set;     }     }

先创建PilotLamp.cs

再创建DelegateEvent.cs:

public delegate void EventHandler();

再创建TrafficLight.cs:

public class TrafficLight : PilotLamp     {     public event EventHandler Notices;    private string notice;    #region GreenLight 成员     public void TurnOn()     {     if (Notices != null)     Notices();     }     public string Notice     {    get    {     return notice;     }    set    {     notice = value;     }     }    #endregion     }

再创建Driver.cs

public class Driver        private string Name;    private PilotLamp greenLight;    public Driver(string name, PilotLamp greenLight)    {    this.Name = name;    this.greenLight = greenLight;    }    public void GoLeft()    {    Console.WriteLine(string.Format("{1}司机,{0},请向左开车.", greenLight.Notice, Name));    }    }

再创建Pedestrian.cs:

 public class Pedestrian     {     private string Name;    private PilotLamp greenLight;    public Pedestrian(string name, PilotLamp greenLight)    {     this.Name = name;     this.greenLight = greenLight;     }    public void GoThrough()     {     Console.WriteLine( string.Format("{0}同志,{1},请向前走.", Name, greenLight.Notice));     }     }

***再调用:

 public partial class Run : Form    {    public Run()     {     InitializeComponent();    }    private void btnRun_Click(object sender, EventArgs e)     {    //-------------------------------------    TrafficLight trafficLight = new TrafficLight();     Driver driverOne = new Driver("张三", trafficLight);    Driver driverTwo = new Driver("李四", trafficLight);    Pedestrian pedestrianOne = new Pedestrian("王五", trafficLight);     Pedestrian pedestrianTwo = new Pedestrian("麻六", trafficLight);     trafficLight.Notices += new Observer.EventHandler(driverOne.GoLeft);     trafficLight.Notices += new Observer.EventHandler(driverTwo.GoLeft);     trafficLight.Notices += new Observer.EventHandler(pedestrianOne.GoThrough);    trafficLight.Notices += new Observer.EventHandler(pedestrianTwo.GoThrough);     trafficLight.Notice = "绿灯亮了.";     trafficLight.TurnOn();    //-------------------------------------     }     }

输出时选控制台应用程序如图:

C#开发中事件与委托机制的示例分析

结果如下图:

C#开发中事件与委托机制的示例分析

事件的使用示例:

 namespace DelegateAndEvent     {     class Program     {     static void Main(string[] args)    {    Publishser pub = new Publishser();    OneScriber oneSub = new OneScriber();     TwoScriber twoSub = new TwoScriber();    ThreeScriber threeSub = new ThreeScriber ();     pub.NumberChanged += new GeneralEventHandler(oneSub.OnNumberChanged);     pub.NumberChanged += new GeneralEventHandler(twoSub.OnNumberChanged);     pub.NumberChanged += new GeneralEventHandler(threeSub.OnNumberChanged);    pub.DoSomething();    }     }     public delegate string GeneralEventHandler();     public class Publishser     {     public event GeneralEventHandler NumberChanged;    public void DoSomething()    {     if (NumberChanged != null)     {     Delegate[] generalEventHandlers = NumberChanged.GetInvocationList();    foreach (Delegate generalEventHandler in generalEventHandlers)     {    GeneralEventHandler mothed = (GeneralEventHandler)generalEventHandler;     string rtn = mothed();     Console.WriteLine(rtn);     System.Threading.Thread.Sleep(2000);     }     }     }     }     public class OneScriber     {     public string OnNumberChanged()     {     return "One Subscriber";     }     }     public class TwoScriber     {     public string OnNumberChanged()     {     return "Two Subscriber";    }     }     public class ThreeScriber     {     public string OnNumberChanged()     {     return "Three Subscriber";     }     }     }

运行结果:

C#开发中事件与委托机制的示例分析

注意到Delegate是GeneralEventHandler 的基类,所以为了触发事件,先要进行一个向下的强制转换,之后才能在其上触发事件,调用所有注册对象的方法。除了使用这种方式以外,还有一种更灵活方式可以调用方法,它是定义在Delegate基类中的DynamicInvoke()方法:

public object DynamicInvoke(params object[] args);

这可能是调用委托最通用的方法了,适用于所有类型的委托。它接受的参数为object[],也就是说它可以将任意数量的任意类型作为参数,并返回单个object对象。上面的DoSomething()方法也可以改写成下面这种通用形式:

代码作如下改动:

namespace DelegateAndEvent    {     class Program     {     static void Main(string[] args)    {     Publishser pub = new Publishser();    OneScriber oneSub = new OneScriber();     TwoScriber twoSub = new TwoScriber();     ThreeScriber threeSub = new ThreeScriber();     pub.NumberChanged += new GeneralEventHandler(oneSub.OnNumberChanged);     pub.NumberChanged += new GeneralEventHandler(twoSub.OnNumberChanged);    pub.NumberChanged += new GeneralEventHandler(threeSub.OnNumberChanged);     List<string> strlist = pub.DoSomething();    foreach (string result in strlist)     Console.WriteLine(result);     System.Threading.Thread.Sleep(5000);     }     }    public delegate string GeneralEventHandler();     public class Publishser    {    public event GeneralEventHandler NumberChanged;     public List<string> DoSomething()     {     List<string> strList = new List<string>();    if (NumberChanged == null) return strList;     Delegate[] generalEventHandlers = NumberChanged.GetInvocationList();     foreach (Delegate generalEventHandler in generalEventHandlers)    {     // GeneralEventHandler mothed = (GeneralEventHandler)generalEventHandler;     string rtn = generalEventHandler.DynamicInvoke(null).ToString();     strList.Add(rtn);    }    return strList;    }     }     public class OneScriber    {     public string OnNumberChanged()    {     return "One Subscriber";     }     }     public class TwoScriber     {     public string OnNumberChanged()     {     return "Two Subscriber";     }     }     public class ThreeScriber     {    public string OnNumberChanged()     {    return "Three Subscriber";     }     }     }

结果如下:

C#开发中事件与委托机制的示例分析

还是一样的结果.

委托的定义会生成继承自MulticastDelegate的完整的类,其中包含Invoke()、BeginInvoke()和EndInvoke()方法。当我们直接调用委托时,实际上是调用了Invoke()方法,它会中断调用它的客户端,然后在客户端线程上执行所有订阅者的方法(客户端无法继续执行后面代码),***将控制权返回客户端。注意到BeginInvoke()、EndInvoke()方法,在.Net中,异步执行的方法通常都会配对出现,并且以Begin和End作为方法的开头(最常见的可能就是Stream类的BeginRead()和EndRead()方法了)。它们用于方法的异步执行,即是在调用BeginInvoke()之后,客户端从线程池中抓取一个闲置线程,然后交由这个线程去执行订阅者的方法,而客户端线程则可以继续执行下面的代码。

BeginInvoke()接受“动态”的参数个数和类型,为什么说“动态”的呢?因为它的参数是在编译时根据委托的定义动态生成的,其中前面参数的个数和类型与委托定义中接受的参数个数和类型相同,***两个参数分别是AsyncCallback和Object类型,对于它们更具体的内容,可以参见下一节委托和方法的异步调用部分。现在,我们仅需要对这两个参数传入null就可以了。另外还需要注意几点:

在委托类型上调用BeginInvoke()时,此委托对象只能包含一个目标方法,所以对于多个订阅者注册的情况,必须使用GetInvocationList()获得所有委托对象,然后遍历它们,分别在其上调用BeginInvoke()方法。如果直接在委托上调用BeginInvoke(),会抛出异常,提示“委托只能包含一个目标方法”。

如果订阅者的方法抛出异常,.NET会捕捉到它,但是只有在调用EndInvoke()的时候,才会将异常重新抛出。而在本例中,我们不使用EndInvoke()(因为我们不关心订阅者的执行情况),所以我们无需处理异常,因为即使抛出异常,也是在另一个线程上,不会影响到客户端线程(客户端甚至不知道订阅者发生了异常,这有时是好事有时是坏事)

BeginInvoke()方法属于委托定义所生成的类,它既不属于MulticastDelegate也不属于Delegate基类, 我们需要进行一个向下转换,来获取到实际的委托类型。

示例:

namespace DelegateAndEvent     {     class Program     {     static void Main(string[] args)     {     Publishser pub = new Publishser();     OneScriber oneSub = new OneScriber();    TwoScriber twoSub = new TwoScriber();     ThreeScriber threeSub = new ThreeScriber();     pub.NumberChanged += new GeneralEventHandler(oneSub.OnNumberChanged);     pub.NumberChanged += new GeneralEventHandler(twoSub.OnNumberChanged);     pub.NumberChanged += new GeneralEventHandler(threeSub.OnNumberChanged);    List<string> strlist = pub.DoSomething();     foreach (string result in strlist)    Console.WriteLine(result);     System.Threading.Thread.Sleep(5000);     }    }     public delegate string GeneralEventHandler(object sender,EventArgs e);     public class Publishser     {    public event GeneralEventHandler NumberChanged;    public List<string> DoSomething()     {    List<string> strList = new List<string>();    if (NumberChanged == null) return strList;     Delegate[] generalEventHandlers = NumberChanged.GetInvocationList();     foreach (Delegate generalEventHandler in generalEventHandlers)     {     GeneralEventHandler mothed = (GeneralEventHandler)generalEventHandler;     IAsyncResult result = mothed.BeginInvoke(this, EventArgs.Empty, null, null);    string str = mothed.EndInvoke(result);     strList.Add(str);    }     return strList;    }     }     public class OneScriber     {    public string OnNumberChanged(object sender,EventArgs e)    {     return "One Subscriber";     }    }     public class TwoScriber     {    public string OnNumberChanged(object sender, EventArgs e)     {    return "Two Subscriber";     }     }     public class ThreeScriber     {    public string OnNumberChanged(object sender, EventArgs e)    {     return "Three Subscriber";    }     }     }

结果:

C#开发中事件与委托机制的示例分析

BeginInvoke的另外两个参数分别是AsyncCallback和Object类型,其中AsyncCallback是一个委托类型,它用于方法的回调,即是说当异步方法执行完毕时自动进行调用的方法。它的定义为:

public delegate void AsyncCallback(IAsyncResult ar);

Object类型用于传递任何你想要的数值,它可以通过IAsyncResult的AsyncState属性获得。

感谢各位的阅读!关于“C#开发中事件与委托机制的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C#开发中事件与委托机制的示例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C#开发中事件与委托机制的示例分析

这篇文章给大家分享的是有关C#开发中事件与委托机制的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。概述C#中的委托类似于C或C++中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该
2023-06-17

C#中的委托和事件实例分析

本文小编为大家详细介绍“C#中的委托和事件实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“C#中的委托和事件实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、定义委托delegate void S
2023-06-30

js事件流、事件委托与事件阶段的示例分析

这篇文章主要介绍了js事件流、事件委托与事件阶段的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1、事件流HTML 中与 javascript 交互是通过事件驱动来实
2023-06-29

.NET中委托与接口的示例分析

这篇文章主要介绍.NET中委托与接口的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!委托:委托是一种定义方法签名的类型。当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。您可以通过委托实例调用方法
2023-06-17

Ext.js4.2.1中事件机制的示例分析

这篇文章主要为大家展示了“Ext.js4.2.1中事件机制的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Ext.js4.2.1中事件机制的示例分析”这篇文章吧。一: 简介Ext中的事件
2023-06-04

Flex事件机制中Flex事件分发和监听的示例分析

这篇文章给大家分享的是有关Flex事件机制中Flex事件分发和监听的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。什么是Flex事件机制Flex事件可以看作是一种触发机制,当满足了一定的条件后,会触发这个
2023-06-17

Android中自定义view中事件分发机制与处理的示例分析

这篇文章将为大家详细讲解有关Android中自定义view中事件分发机制与处理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。题引事件只有一个,多个人想要处理,处理的对象不是我们想给的对象就是事件
2023-06-25

Flex事件机制的示例分析

这篇文章主要为大家展示了“Flex事件机制的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Flex事件机制的示例分析”这篇文章吧。什么是Flex事件机制Flex事件可以看作是一种触发机制
2023-06-17

JS中事件循环机制的示例分析

小编给大家分享一下JS中事件循环机制的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1、JavaScript是单线程的JavaScript 是一种单线程的
2023-06-29

nodejs中事件循环机制的示例分析

这篇文章主要介绍了nodejs中事件循环机制的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前端开发离不开JavaScript,Javascript是一种web前端语
2023-06-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录