C# 委托与事件
本文最后更新于 444 天前,其中的信息可能已经有所发展或是发生改变。

前言

在应用开发中,我们经常会遇到当用户触发了某个事件后,需要处理这个事件对应的函数。

在这里我们引入了delegateevent来应对这种情况。

实现

举个例子

假如我要写一个看到人摔跤,就要上前将他扶起来并且确认有无大碍的程序。

public class Person
{
    public Person(bool healthy, string name)
    {
        this.healthy = healthy;
        this.name = name;
    }

    public bool healthy { get; set; }
    public string name { get; set; }
}

正常来讲可以这样实现:

Person p = new Person() { healthy = true,name = "小明"};
Console.WriteLine("{0}摔倒了",p.name);
holdUp(p);
isHealthy(p);



static void holdUp(Person p)
{
    Console.WriteLine("扶起了{0}", p.name);
}

static void isHealthy(Person p)
{
    Console.WriteLine("健康:{0}", p.healthy);
}

Output:

小明摔倒了
扶起了小明
健康:True

Delegate

但是引入了delegate委托后,我们可以通过

public class Handler
{
    public delegate void PersonHandler(Person p); //这里C#我用了顶级语句,所以额外创建一个类存放委托
}

此处委托的定义类似于声明变量,但其实这是一种对类型的声明,可以在类中、直接在命名空间中、甚至是在全局命名空间中定义委托类型。于是在使用的时候,我们可以直接声明实例:

Handler.PersonHandler handler = new Handler.PersonHandler(holdUp);
handler += isHealthy;

Person p = new Person(true, "小明");
Console.WriteLine("{0}摔倒了", p.name);
handler(p);

Output:

小明摔倒了
扶起了小明
健康:True

在这里,C#将方法附加到了委托上,通过一次触发,将附加到委托上的方法像放鞭炮一样按顺序点燃。

建议不要直接在全局命名空间中声明委托类型(或其他类型)。

Event

如果说delegate就是点鞭炮的打火机,那么event就是拿打火机的人,我们可以通过event来点火触发委托。

为Person类加入

  public bool isFall { get; set; }

在Handler类中加入

  public static event PersonHandler PersonEvent;

添加方法

public static void check(Person p)
{
    Timer timer = new Timer();
    timer.Elapsed += (o, s) => 
    {
        /*
         * if(Tick){OnFall(Person p);} //触发事件
         */
        if (p.isFall) onFall(p);
     };
    timer.Interval = 1000;
    timer.Start();
}

private static void OnFall(Person p)
{
    PersonEvent(p);
}

该方法的作用是调用新线程,监听Person.isFall是否为真,若为真则触发OnFall()方法,再点燃event。

在程序入口中,我们要为event绑定委托,这样event才能知道要点燃哪些鞭炮。

Handler.PersonEvent += new Handler.PersonHandler(holdUp);
Handler.PersonEvent += new Handler.PersonHandler(isHealthy); //绑定委托

Person p = new Person(true, "小明",false);
Handler.check(p);
p.isFall = true; //小明摔了
Console.WriteLine("{0}摔倒了", p.name);
Thread.Sleep(1000); //主线程挂起休眠

Output:

小明摔倒了
扶起了小明
健康:True

总结

简单来说,一个简单的事件触发由发布-订阅[publisher-subscriber] 模型构成。

  • 发布器(publisher) 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。
  • 订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。在发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。

在上述例子中,Handler类相当于发布器的角色,而holdUp与isHealthy应该是属于订阅器类的方法,通过这样一个简单的模型我们便可以完成监听+执行的行为。

 

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇