关于c#中委托与事件的一些理解

文章目的:作者(初学者)在学习c#的过程中,对事件、委托及其中的“object sender,EventArgs e”一直感觉理解不透,因此在网上找了一些资料,学习并整理出了该篇笔记,希望能将自己的心得记录下来作为积累。限于能力且是初学,有错误的地方还请大家批评指正。

注意:该笔记中有部分内容摘自网上的参考资料,并非作者原创,仅限学习交流,特此声明!

一. 委托与事件

      委托与事件是一对相互关联的概念。委托是一种引用类型,可通过声明委托变量,并将其初始化为某个匹配的函数来实现对该函数的引用。事件可以使类或对象向其他类或对象通知发生的相关事情,以使其他类或对象为此做出响应。灵活的事件处理要求将事件的响应分派给相应的事件处理程序(或称事件处理函数、事件处理方法),而C#中事件处理程序通常都是委托实现的。

二. 委托

  1. 定义

    委托其实是一种引用类型,它通过声明一个委托类型的变量,并通过将该变量初始化一个与该委托具有相同返回值类型和形参列表的函数引用,来实现所谓的对函数的引    用。

  2. 声明方式

    modifiers(opt)      delegate           return-Type        identifier         fomal-parameter-listopt))

            修饰符(可选)        委托关键字        返回值类型             标识符              (形参列表(可选)

            Public                    delegate           double                DataProcess     (double x, double y)

  3. 使用步骤

    1)声明委托,指定其返回值类型和形参列表;

     2)定义与委托具有相同返回值类型和形参列表的函数;

     3) 声明委托类型的变量,并将该委托变量初始化为步骤2)中所定义的与该委托具有相同返回值类型和形参列表的函数引用.

  4. 使用举例

1 public delegate double DataProcess(double x, double y);//声明委托DataProcess,指定其返回值类型和形参列表
2 class A
3 {
4   public static double Multiply(double x, double y);  //定义与委托具有相同返回值类型和形参列表的函数Multiply()
5    {
6      return x*y;
7    }
8   DataProcess dataProcess = new DataProcess(Multiply);//定义了委托之后,声明该委托类型的变量dataProcess,接着把这个变量初始化为与委托具有相同返回值类型和                                                           //形参列表的函数引用Multiply
9 }

三. 事件

  1. 定义

    1)发起者:引发事件的类或对象;

    2) 订户:处理(或称“响应”)事件的类或对象;

    3) 事件处理程序:订户提供的一些代码,用于在事件被引发时执行(事件处理程序可位于发起者所在的类,也可位于其他类);

    4) 订阅:在发起者引发事件后,执行订户的事件处理程序(即将事件处理程序绑定到事件);

    5) 事件:事件由发起者引发,由订户订阅,事件被引发后开始执行订阅该事件的由订户所提供的事件处理程序;

  2. 声明方式

    modifiers(opt)         event              Type                     identifier   

    修饰符(可选)          委托关键字         类型                      标识符    

    Public                      event               EventHanlder       Click

四。 事件的分类及其使用步骤

  这里将事件分为两种:1.NetFrameWork类库中已经为我们封装好的事件;2.我们自定义的事件。下面分别说明这两种事件的使用步骤,并给出代码示例:

  1.NetFrameWork类库中封装好的事件的使用步骤

    注意:在.NET Framwork类库中,事件是基于EventHandler(委托祖类)和EventArgs(事件数据祖类)两个基类的。

    1)定义委托

      委托的定义用于指定订阅该事件的事件处理程序(或事件处理方法、事件处理函数)的返回值类型及形参列表(此处以backgroundWorker组件为例);     

             public   delegate   void   DoWorkEventHandler ( object sender,  DoWorkEventArgs e);         a. 返回值类型:void      b. 参数1:object sender:       是一个对象,其实是一个对象引用,这里的事件是对象backgroundWorker1的事件,这个对象指的就是backgroundworker1。(backgroundWorker1是B               ackgroundWorker类的一个实例)。      c. 参数2:DoWorkEventArgs e:             是一个包含事件数据的对象,用于传递事件的细节,DoWorkEventArgs是一个包含事件数据的类,它继承自包含事件数据的基类EventArgs;

     注意:委托的返回值类型和形参列表根据自己的需要定义(包括命名),只要事件处理方法的返回值和参数与之匹配即可。此外委托并不需要与事件位于同一个类或              命名空间中,它可以位于其他类或命名空间,在.Net Framwork的类库中就是这样,自定义事件可根据需要安排。   2)定义事件     
1 public  event  DoWorkEventHandler  DoWork;

      该事件位于BackgroundWorker类中,所以调用时为this.backgroundWorker1.DoWork,该事件在RunWorkerAsync()函数中引发,该函数也位于         BackgroundWorker类中。

    3)定义监听事件函数(监听事件函数用于在满足一定条件时引发事件)

     事件DoWork的监听事件函数是RunWorkerAsync(),该函数已经由.NET在BackgroundWorker类中定义,我们直接用就可以。         4)定义事件处理函数    
private void Process(object sender, DoWorkEventArgs e)
{
        Console.writeln(“the event has processed!”);
}

    注意:要求事件处理函数与委托具有匹配的返回值类型和参数列表。

    5)为事件添加事件处理函数

     
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(Process);

    以上便是.net类库封装的事件的使用过程,但是事件处理函数的添加一般在组件(或控件)的属性中设置即可,另外委托、事件和监听事件函数.NET Framework类     库已经为我们定义好,直接用就可以,我们唯一需要做的就是编写事件处理函数,我们可以在事件处理函数中写入事件发生时我们想做的事情。

  2.自定义事件使用步骤(这里以一个类来监听客户端键盘输入事件为例)

    1)定义委托

      

public delegate void UserRequest(Object sender, EventArgs e);

      注意:参数Object用来传递事件的发生者,EventArgs用来传递事件的细节(该例暂时没用到)。

    2)定义事件 (步骤1)中的委托类型

      

public event UserRequest OnUserRequest;

    3)定义监听事件函数

      监听事件函数用于在满足一定条件时引发事件,监听事件函数对于在.NET Framwork类库中封装的事件已经为我们定义好了,无需我们自己定义。而这里我们需要自    己定义,此函数相当于事件使用步骤1中的RunWorkerAsync()函数

//该函数不断要求用户从键盘输入字符,如果输入结果为“h”,则引发OnUserRequest事件,事件的引发者是本身(this,即该类(或该类实例化对象)),事件细节无(没有传递任何参数给E//ventArgs实例),我们给这个类起名为UserInputMonitor。
public void run()
        {
            bool finished = false;
            do
            {
                if (Console.ReadLine() == "h")
                {
                    OnUserRequest(this,new EventArgs());//如果用户键盘输入为“h”,则引发事件
                }
            } while (!finished);
        }  

    4)定义事件处理程序(这里将该函数定义在客户端类(Client类)中)

      首先实例化UserInputMonitor类:

UserInputMonitor monitor = new UserInputMonitor();

      然后定义事件处理程序

private void ShowMessage(object sender, EventArgs e)
{
    Console.WriteLine("haha");//如果用户输入的h,则打印“haha”
}

    5)将事件处理程序绑定到事件(或称订阅事件)

      这里将其写到Client的构造函数里

Client(UserInputMonitor m)
{
     m.OnUserRequest += new UserInputMonitor.UserRequest(this.ShowMessage);
}

      接下来创建客户端并开始监听事件

new Client(monitor);//将事件处理方法绑定到事件OnUserRequest
monitor.run();

  该自定义事件的全部代码如下所示(c#控制台程序)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{

    class Client
    {
        //构造函数
        Client(UserInputMonitor m)
        {
            m.OnUserRequest += new UserInputMonitor.UserRequest(this.ShowMessage);//订阅事件
        }

        public static void Main(string[] args)
        {
            UserInputMonitor monitor = new UserInputMonitor();
            new Client(monitor);//将事件处理方法绑定到事件OnUserRequest
            monitor.run();
        }

        private void ShowMessage(object sender, EventArgs e)
        {
            Console.WriteLine("haha");
        }
}

    class UserInputMonitor
    {
        public delegate void UserRequest(Object sender, EventArgs e);//定义委托

        public event UserRequest OnUserRequest;//定义此委托类型的事件

        public void run()
        {
            bool finished = false;
            do
            {
                if (Console.ReadLine() == "h")
                {
                    OnUserRequest(this,new EventArgs());//如果用户键盘输入为“h”,则事件发生
                }
            } while (!finished);
        }

    }
}
时间: 2024-10-12 11:35:16

关于c#中委托与事件的一些理解的相关文章

C#中委托和事件的区别实例解析

这篇文章主要介绍了C#中委托和事件的区别,并分别以实例形式展示了通过委托执行方法与通过事件执行方法,以及相关的执行流程与原理分析,需要的朋友可以参考下 本文实例分析了C#中委托和事件的区别,分享给大家供大家参考之用.具体如下: 大致来说,委托是一个类,该类内部维护着一个字段,指向一个方法.事件可以被看作一个委托类型的变量,通过事件注册.取消多个委托或方法.本篇分别通过委托和事件执行多个方法,从中体会两者的区别. 一.通过委托执行方法 1 2 3 4 5 6 7 8 9 10 11 12 13 1

c#中委托和事件(转)

C# 中的委托和事件 引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在.本文中,我将通过两个范例由浅入深地讲述什么是委托.为什么要使用委托.事件的由来..Net Framework中的委托和事件.委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论. 将方法作为方法的参

C#中委托和事件

目 录 1.1 理解委托 2 1.1.1 将方法作为方法的参数 2 1.1.2 将方法绑定到委托 4 1.2 事件的由来 6 1.2.1 更好的封装性 6 1.2.2 限制类型能力 9 1.3 委托的编译代码 10 1.4 .NET 框架中的委托和事件 11 1.4.1 范例说明 11 1.4.2 Observer 设计模式简介 12 1.4.3 实现范例的Observer 设计模式 13 1.4.4 .NET 框架中的委托与事件 14 1.5 委托进阶 16 1.5.1 为什么委托定义的返回值

C#中委托和事件的区别

大致来说,委托是一个类,该类内部维护着一个字段,指向一个方法.事件可以被看作一个委托类型的变量,通过事件注册.取消多个委托或方法.本篇分别通过委托和事件执行多个方法,从中体会两者的区别. □ 通过委托执行方法 class Program { static void Main(string[] args) { Example example = new Example(); example.Go(); Console.ReadKey(); } } public class Example { pu

c#中委托和事件(续)(转)

本文将讨论委托和事件一些更为细节的问题,包括一些大家常问到的问题,以及事件访问器.异常处理.超时处理和异步方法调用等内容. 为什么要使用事件而不是委托变量? 在 C#中的委托和事件 中,我提出了两个为什么在类型中使用事件向外部提供方法注册,而不是直接使用委托变量的原因.主要是从封装性和易用性上去考虑,但是还漏掉了一点,事件应该由事件发布者触发,而不应该由客户端(客户程序)来触发.这句话是什么意思呢?请看下面的范例: NOTE:注意这里术语的变化,当我们单独谈论事件,我们说发布者(publishe

C#中委托和事件的理解

看了张子阳博客后,总结了一下个人的理解,原文见:http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html 委托是可以把方法作为参数的一种东东. 把委托声明成与方法的返回值和参数一模一样. 然后把方法赋值给委托变量,委托变量就可以作为参数带入函数. 委托最主要的作用是实现C#中的事件. C#中的委托型事件需要遵守几个书写规范: 1.委托名称必须以EventHandler结尾.如:PlayEventHandler 2.委托必须声

c#中委托与事件的关系

C#中的事件处理实际上是一种具有特殊签名的delegate,象下面这个样子:public delegate void MyEventHandler(object sender, MyEventArgs e);其中的两个参数,sender代表事件发送者,e是事件参数类.MyEventArgs类用来包含与事件相关的数据,所有的事件参数类都必须从System.EventArgs类派生.当然,如果你的事件不含参数,那么可以直接用System.EventArgs类作为参数. 就是这么简单,结合delega

C#中 委托和事件的关系

首先,委托 是一个好东西.按我的理解,委托 是针对 方法 的更小粒度的抽象.比较interface,他精简了一些代码.使得 订阅-通知 (观察者模式)的实现变得非常简洁. 关于事件,我最初的理解是:事件是利用委托  对  通知-订阅模式 的一种实现方式. 我觉得我并没有理解错,但还不够精确. 我现在要问: 为什么要用非要事件来实现 通知-订阅模式? 而不直接用委托呢?事件到底解决了什么问题? 在<果壳中的C# 中文版> P112页 说了. 总的目标是 事件-订阅 模式中,保护订阅互不影响. 如

C# 中的委托和事件

http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html 文中代码在VS2005下通过,由于VS2003(.Net Framework 1.1)不支持隐式的委托变量,所以如果在一个接受委托类型的位置直接赋予方法名,在VS2003下会报错,解决办法是显式的创建一个委托类型的实例(委 托变量).例如:委托类型 委托实例 = new 委托类型(方法名); 欢迎浏览本文的后续文章: C#中的委托和事件(续) 引言 委托 和 事件在