C# event 事件

  曾经面试碰到一道设计题:

  现有一个人,一群鸟,人有一把手枪,当人开枪时,所有的鸟都被吓飞了。要求按照题干设计程序且有一定的扩展性。

当时我并无任何的程序设计知识,看到该题一点解决办法也没有,按照面向过程完全可以写流程出来,但“光写流程”并不符合C#面向对象的的思想,写出来也不具有任何扩展性。

直到后来学习了事件的相关知识,可能目前仍然不清楚如何扩展,但至少可以写个像模像样的程序出来。

1.事件的组成

事件的组成分为5个部分:

(1)事件的拥有者

(2)事件本身

(3)事件的订阅者

(4)事件处理器

(5)订阅事件

  事件的拥有者,或者说这件事的发起者,以上题为例,人开枪,人便是发起事件的对象,是事件的拥有者;事件的本身,开枪这件事便是事情的本身;事件的订阅者,也就是关注事件发生的对象,题中开枪后鸟都飞走了,鸟是听到枪响才飞走的,也就是说鸟是关注“开枪”这件事的对象;事件处理器,订阅者在关注到事件发生后,针对事件作出的反应。鸟在枪响后都被吓得飞走了,“飞走”便是它们针对“开枪”作出的事件处理。此外,事件的发生和事件处理都是一种动作,两者紧密相连却又互不相同,在处理事件的逻辑时一定要分清二者的界限,切不可混为一谈而导致逻辑混乱;而订阅事件,这实际是一种关系,这个关系是联系拥有者和订阅者、事件和事件处理的一个“纽带”。就好比你家里做好了饭,家里人通知你饭做好了,你知道要开饭了于是赶紧回家,因为你是“关注”家里“开饭”这件事的,这便是订阅事件。

2.事件的使用

  定义事件的关键字是event,并且事件定义时需要搭配委托,语法:修饰符 + event + 委托类型 + 名称。

  事件的触发只能在被声明该事件的类中进行,语法与类方法调用相同,所以事件是不能直接在类体之外触发的,若想在程序的其他地方触发方法,必须要用类方法在类体中封装事件。

  事件的订阅需要用到“+=”操作符,语法:实体类名称.事件 += 方法(事件处理器)。由于事件依托委托来声明,所以一个事件可以挂接多个事件处理器,也就是说可以被多个对象订阅。

  回到题目,理清楚题目中的对象分别对应组成事件的哪个部分,人是事件的发起者、开枪是事件本身,鸟是事件的订阅者,它订阅了开枪这件事,而飞走是它对开枪这件事的处理。写成代码大概是下面这个样子:

//人

public class Man
{

  //人的事件(这里用了执行无参数无返回值方法的委托类型)
  public event Action Fire;

  //封装了事件的类方法

  public void Action()
  {
    if (Fire != null)
    {
      Console.WriteLine("人开枪了");
      //触发事件

      Fire();
    }
  }  
}

//鸟

public class Bird
{
  public string birdName { get; set; }

  //声明一个集合类型的静态字段,用于保存实例化的所有Bird类

  public static List<Bird> Birds = new List<Bird>();

  //这是鸟类对于开枪的事件处理器

  internal static void Fly()
  {
    for (int i = 0; i < Birds.Count; i++)
    {
      Console.WriteLine(Birds[i].birdName + "飞走了");
    }
  }

  //每一次实例化都会在构造函数中保存当前实例化的Bird类

  public Bird()
  {
    Birds.Add(this);
  }
}

class Program
{
  static void Main(string[] args)
  {

    //实例化对象
    Man man = new Man();

    //订阅事件,联结两类对象中的事件和事件处理器
    man.Fire += Bird.Fly;

    //循环生成Bird类
    for (int i = 0; i < 5; i++)
    {
      Bird bird = new Bird();
      bird.birdName = "小鸟" + i;
    }

    //调用封装事件的方法,触发事件
    man.Action();
  }

}

  

猜你喜欢

转载自www.cnblogs.com/FavoriteMango/p/11685702.html