C#中的delegate和event简单示例

    C# 中的“事件”是当对象发生某些有趣的事情时,类向该类的客户提供通知的一种方法。事件最常见的用途是用于图形用户界面;通常,表示界面中的控件的类具有一些事件,当用户对控件进行某些操作(如单击某个按钮)时,将通知这些事件。比如在进行网络操作时,由于网络请求很耗时,因此网络请求应该为异步,调用者并不知道请求何时完成,因此就需要使用事件来注册回调函数,当网络请求完成时触发事件,从而执行对于的回调函数获取到请求的结果。

    但是事件未必只用于图形界面。事件为对象提供一种通常很有用的方法来发出信号表示状态更改,这些状态更改可能对该对象的客户很有用。事件是创建类的重要构造块,这些类可在大量的不同程序中重复使用。

    使用委托来声明事件。如果您尚未学习“委托教程”,您应先学习它,然后再继续。请回忆委托对象封装一个方法,以便可以匿名调用该方法。事件是类允许客户为其提供方法(事件发生时应调用这些方法)的委托的一种方法。事件发生时,将调用其客户提供给它的委托。

一般步骤:
  • 声明事件   若要在类内声明事件,首先必须声明该事件的委托类型(如果尚未声明的话,注意到事件和委托类型的名字是一样的)。
    public delegate void ChangedEventHandler(object sender, EventArgs e);
    

    委托类型定义传递给处理该事件的方法的一组参数。多个事件可共享相同的委托类型,因此仅当尚未声明任何合适的委托类型时才需要执行该步骤。

    接下来,声明事件本身。

    public event ChangedEventHandler Changed;
    

    声明事件的方法与声明委托类型的字段类似,只是关键字 event 在事件声明前面,在修饰符后面。事件通常被声明为公共事件,但允许任意可访问修饰符。

  • 调用事件   类声明了事件以后,可以就像处理所指示的委托类型的字段那样处理该事件。如果没有任何客户将委托与该事件挂钩,该字段将为空;否则该字段引用应在调用该事件时调用的委托。因此,调用事件时通常先检查是否为空,然后再调用事件。
    if (Changed != null)
    {
        Changed(this, e);
    
    }

    调用事件只能从声明该事件的类内进行。

  • 与事件挂钩   从声明事件的类外看,事件像个字段,但对该字段的访问是非常受限制的。只可进行如下操作:
    • 在该字段上撰写新的委托。
    • 从字段(可能是复合字段)移除委托。

    使用 += 和 -= 运算符完成此操作。为开始接收事件调用,客户代码先创建事件类型的委托,该委托引用应从事件调用的方法。然后它使用 += 将该委托写到事件可能连接到的其他任何委托上。

    // 添加"ListChanged"事件到List对象中
    List.Changed += new ChangedEventHandler(ListChanged);
    

    当客户代码完成接收事件调用后,它将使用运算符 -= 从事件移除其委托。

    // 移除该事件
    List.Changed -= new ChangedEventHandler(ListChanged);

简单示例 :

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

namespace delegateEventDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Request req = new Request();
        }

        static void print(String msg)
        {
            System.Console.WriteLine(msg);
        }


        /// <summary>
        /// 调用异步任务的类
        /// </summary>
        class Request
        {
            public Request()
            {
                AsyncRequestDemo d = new AsyncRequestDemo();
                // 注册事件触发时的回调函数来接收结果
                d.addCompleted += d_addCompleted;
                // 模拟异步调用
                d.AsyncAdd(3, 8);
            }

            /// <summary>
            /// 异步调用的回调函数,通过事件传递回来参数
            /// </summary>
            /// <param name="result"></param>
            void d_addCompleted(int result)
            {
                print("计算结果为 : " + result);
            }

        }


        /// <summary>
        /// 被调用的类,包含事件和代理
        /// </summary>
        class AsyncRequestDemo 
        {

            // 代理与事件的类型名要一样
            public delegate void myAsyncAddDelegate(int result);
            // 与上面的代理同名的事件类型,在事件触发时会调用在main中的回调函数d_addCompleted()
            public event myAsyncAddDelegate addCompleted;

            /// <summary>
            /// 带参数的类型
            /// </summary>
            /// <param name="a">被加数a</param>
            /// <param name="b">被加数b</param>
            /// <returns></returns>
            public void AsyncAdd(int a, int b)
            {
                /*
                 * 假设这里是异步操作,当异步完成时,调用自身的addCompleted事件,并且传递结果作为参数,
                 * 这样在Request类中的对应回调函数就可以接收计算结果了。
                 */
                print(String.Format("**** 三八节快乐 **** 异步调用 AsyncAdd {0} + {1} ", a , b) );

                int result = a + b;
                // 将结果通过触发事件返回
                this.addCompleted(result);
            }

        }
    }
}

结果为 :


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值