事件部分知识补充点

转载来源:https://zhuanlan.zhihu.com/p/162065756
Order是事件,这种Invoke就是无法在外部实现的,事件的触发只能由事件的拥有者自己来做。
——需要强调的是,简化声明时Invoke可以在类体内被调用——这是一种不得已而为之的语法:因为简化声明时没有手动声明一个委托类型的字段来作为约束器供类体内调用。

事件的相关命名规则整合及总结
1>.用于约束和声明事件Hungry的委托,一般命名为HungryHandler(除非是某些非常通用的事件约束器)

2>.HungryEventHandler委托一般有两个参数(由Win 32 API演化而来,历史非常悠久)

·第一个参数是obejct类型的实例sender,规定了事件发送者是谁,也规定了处理器 响应谁的事件;任何消息的发送者都肯定是个对象,而所有对象都是object的子类实 例

· 第二个参数是EventArgs的派生类的实例e,这个派生类的类名一般是HungryEventArgs,参数名为e,又称事件参数;这个事件参数实际上就是事件发送者发送给响应者的“事件消息”,响应者根据这个事件消息来处理事件。(事件参数e所包含的数据是事件处理器加工件所用的参数)——函数是数据的加工厂!

3>.触发Hungry事件的方法一般命名为OnHungry,即“因何而发”,“事出有因”:因为我这个事件被触发了,所以这个方法被调用了

·这个OnHungry的访问级别是protectd,不能为public,不然又能“借刀杀人”了。

protected修饰的对象只能从当前类或当前类的派生类访问。

4>.因为单一职责原则,OnHungry方法一般只用于触发事件,类似上面例子里的think方法又负责思考又负责调用事件(这个方法做了两件事)的写法是不规范的。

可以修改为:

   public void Think()
        {
         for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("该吃点什么呢....");
                Thread.Sleep(1000);
            }
         //如果实例order事件的约束器不为空就调用事件
        if (this.orderEventHandler != null)
            {
                OnOrder(DishType.big, "Cheese Fries");
            }             
        }
        protected void OnOrder(DishType dishType,string dishName)
        {
            OrderEventArgs e = new OrderEventArgs();
            e.DishType = dishType;
            e.DishName = dishName;
            this.orderEventHandler.Invoke(this,e);
        }

5>.在触发事件时要先判断事件处理器是否为空

6>.在命名事件时使用带有时态的动词或者动词短语

·事件拥有者“正在做”什么事就用进行时,“做完了”什么事就用完成时

事件与委托的关系及谬误辨析
事件是“以特殊方式声明的委托字段/实例吗?”

不是!

只是声明时看起来有点像而已

·事件的声明使用委托类型来约束,简化声明使事件看起来就像一个委托的字段(实例),而event关键字则像是一个修饰符,这是错觉的来源之一

访问修饰符 event 约束器类型 事件名;

这里的“约束器类型”正是委托的类型

·订阅事件时的+=操作符后面可以是一个委托的实例,这与委托实例的赋值方法语法相同,也让事件看起来像一个委托字段——这是错觉的另一个来源

(+=既可以用于给事件挂载处理器,也可以给委托用来挂载委托所要“托管”的方法,这里的托管是调用的意思)

强调:事件的本质是委托上的一个蒙版[Mask],是用于隐蔽委托功能的包装器,这个用于阻挡非法访问的Mask绝不是委托字段本身。

为什么要以委托类型来声明事件?

·站在source角度来看,是为了表明source所能对外传递的信息

·站在subscirber[订阅者]角度看,这个委托是一种约定,用于约束能使用什么样签名的方法来处理(响应)事件

·委托类型的实例用于存储(引用)事件的处理器

对比事件和属性

·属性不是字段——很多时候属性是字段的包装器,这个包装器保护字段不被滥用

·属性不是委托字段——它是委托字段的包装器,这个包装器用来保护委托字段不被滥用

·包装器永远不可能是被包装的东西

posted @ 2022-01-21 16:10  跨界专家  阅读(66)  评论(0)    收藏  举报