C# 教程 在线

2431C# 事件(Event)

一个很简单的例子:当宠物店有新狗时通知订阅客户。

using System;

namespace BoilerEvent
{
    class Dog
    {
        private String name;
        private String color;

        public delegate void Handeler(); //定义委托
        public static event Handeler NewDog;  //定义事件

        public  Dog(String Name, String Color)
        {
            name = Name;
            color = Color;
            if (NewDog != null)
            {
                Console.WriteLine("新进了一只狗");
                NewDog();  //调用事件
            }
        }
    }

    class Test
    {
        public static void Main(String[] args)
        {
            Dog d = new Dog("Tony","yellow"); //因为还没有添加订阅,所以不能触发事件
            Dog.NewDog += new Dog.Handeler(Client1); //Client1添加订阅
            Dog.NewDog += new Dog.Handeler(Client2);//Client2添加订阅
            Dog d2 = new Dog("Tom", "white"); 
        }
        static void Client1()
        {
            Console.WriteLine("我喜欢这条狗!");
        }
        static void Client2()
        {
            Console.WriteLine("我非常想要!");
        }
    }
}

2430C# 事件(Event)

明明可以很简单(对实例1的简单修改):

using System;
namespace SimpleEvent
{
  /***********发布器类***********/
  public class EventTest
  {
    public delegate void NumManipulationHandler(); //声明委托
    public event NumManipulationHandler ChangeNum; //声明事件

    public void OpenDoor()
    {
        ChangeNum();  //事件触发
    }
  }

  /***********订阅器类***********/
  public class subscribEvent
  {
    public void printf()
    {
      Console.WriteLine( "The door is opened." );
    }
  }

  /***********触发***********/
  public class MainClass
  {
    public static void Main()
    {
      EventTest e = new EventTest(); /* 实例化事件触发对象 */
      subscribEvent v = new subscribEvent(); /* 实例化订阅事件对象 */
        
        /* 订阅器的printf()在事件触发对象中注册到委托事件中 */
      e.ChangeNum += new EventTest.NumManipulationHandler( v.printf ); 
      e.OpenDoor(); /* 触发了事件 */
    }
  }
}

2429C# 事件(Event)

事件的运用总结

事件的整个过程是:订阅 -> 发布 -> 执行

  • 订阅: 假设事件 A 的执行方法是 F_A,事件 B 的执行方法是 F_B,将这些事件与它们的委托人进行绑的行为就是订阅,这个委托人就是发布器的一个成员。订阅器另一个行为就是在订阅之后(必学先订阅)通知发布器的相关成员。
  • 发布: 首先要明确事件发布的类型(由事件的执行方法参数列表决定)和要发布事件的变量(这个变量即委托人);其次整理发布所需的材料、判断条件是否合适等;最后让内部的委托人向执行函数传递最终信息。
  • 执行: 是整个事件最后完成的步骤,就是普通的函数。

2428C# 事件(Event)

实例:

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

namespace BoilerEvent_tz
{
    class DelegateTest   // 发布器类
    {
        public delegate void delegate_tz();
        public event delegate_tz delegate_tz0;
        public static void get()
        {
            Console.WriteLine("这是触发事件的第一个方法,此方法在事件类中");
        }
        public void inter()
        {
            Console.WriteLine("开始调用事件方法");
            delegate_tz0();
        }
    }

    class Test // 订阅器类
    {
        public Test()
        { }
        public void TryEvent()
        {
            Console.WriteLine("这是触发事件的第三个方法,在订阅器中,这才是正宗的订阅器类");
            Console.ReadKey();
        }
    }

    class Program //主体函数 程序入口
    {
        static void Main(string[] args)
        {
            DelegateTest DelegateTest0 = new DelegateTest();
            //主体函数中根据需求组装事件,组装过程类似委托多播
            DelegateTest0.delegate_tz0 += new DelegateTest.delegate_tz(DelegateTest.get);
            DelegateTest0.delegate_tz0 += new DelegateTest.delegate_tz(Method1);
            DelegateTest0.delegate_tz0 += new DelegateTest.delegate_tz(new Test().TryEvent);
            DelegateTest0.inter();                                                  // 执行操作,以触发事件
        }

        static public void Method1()
        {
            Console.WriteLine("这是触发事件的第二个方法,在主体Main函数中");
        }
    }
}

执行输出结果为:

开始调用事件方法
这是触发事件的第一个方法,此方法在事件类中
这是触发事件的第二个方法,在主体Main函数中
这是触发事件的第三个方法,在订阅器中,这才是正宗的订阅器类

2427C# 事件(Event)

delegate 相当于定义一个函数类型。

event 相当于定义一个 delegate 的函数指针(回调函数指针)。

这样就好理解了。