C#中事件只能在内部调用的原因分析

在学习C#中委托和事件时,产生一个疑问,类中定义的事件在类内部可以直接调用,而在类外部,事件却只能添加或移除委托方法

比如下面这段代码,类Customer中定义了一个委托 Order ,Customer内部可以直接调用 Order.Invoke()

public class Customer
    {
     	// 定义事件
        public event  OrderEventHandler Order;
        public string? name;
        public float? price;
        protected void onOrder(OrderEventArgs orderEventArgs)
        {
            if(Order != null)
            {
                Order.Invoke(this, orderEventArgs);
            }
        }
     ......

而在类的外部,只能添加或移除委托方法,不能调用Order.Invoke(),下面代码中customer.Order.Invoke()会报错。

public class Program{
        public static void Main(string[] args)
        {
            var customer = new Customer();
            customer.name = "1";
            Waiter waiter = new Waiter();
            customer.Order += waiter.Serve;
           //  customer.Order.Invoke() 这样写无法编译
            customer.Think();
            customer.Pay();
        }
    }

细看刘铁猛老师的《C#入门详解》后,才明白原来这是C#语法糖让我产生的误解,在定义事件时,

下面这行代码是常见的定义方式,这是一种简明的定义方法

// 事件的简明定义方式
public event  OrderEventHandler Order;
而C#中事件完整的定义方式是这样:
        private OrderEventHandler orderEventHandler;//委托,使用private 修饰
        public event  OrderEventHandler Order // 事件,对委托方法进行增减
        {
            add
            {
                this.orderEventHandler += value;
            }
            remove
            {
                this.orderEventHandler -= value;
            }
        }

使用完整写法定义事件后,在内部调用也不能用事件Order去调用了,要用委托去调用

     protected void onOrder(OrderEventArgs orderEventArgs)
        {
            if(this.orderEventHandler != null)
            {
                // 调用委托
                this.orderEventHandler.Invoke(this, orderEventArgs);
            }
        }

可以看到,我们真正调用的委托使用private修饰,是私有的,所以只能在内部调用,而事件(event)则是对私有的委托进行了包装,实现对委托方法的增加或移除。

刚学C#,不知道说清楚没。。。

到此这篇关于C#中事件为什么只能在内部调用的文章就介绍到这了,更多相关C#事件内部调用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C#通过委托调用Button单击事件的方法

    这里介绍通过委托取消Button事件switch-case的方法.需要注意的是,事先要按顺序在各个Button的Tag属性中设置0.1.2.3--等序号,其作用请详看代码. /*定义委托*/ public delegate 类型或viod MethodDelegate(参数1, 参数2); private void buttonC_Click(object sender, EventArgs e) { Button button = (Button)sender; /*向委托添加方法*/ Met

  • C#中事件的动态调用实现方法

    本文实例讲述了C#动态调用事件的方法.一般来说,传统的思路是,通过Reflection.EventInfo获得事件的信息,然后使用GetRaiseMethod方法获得事件被触发后调用的方法,再使用MethodInfo.Invoke来调用以实现事件的动态调用. 但是很不幸的,Reflection.EventInfo.GetRaiseMethod方法始终返回null.这是因为,C#编译器在编译并处理由event关键字定义的事件时,根本不会去产生有关RaiseMethod的元数据信息,因此GetRai

  • C#中WebBrowser.DocumentCompleted事件多次调用问题解决方法

    关于DocumentCompleted事件,MSDN给出的解释是在文档加载完毕后执行,但是在我的程序中DocumentCompleted却被多次调用,查了一下资料,大概出现了以下几种情况. 1.WebBrowser载入一个页面后DocumentCompleted事件会执行两次,但这两次的ReadyState状态不一样,分别是Intercative和Complete.而MSDN对这两种状态值的解释是:Complete该控件已完成新文档及其所有内容的加载:Interactive该控件已经加载足够的文

  • C#中事件只能在内部调用的原因分析

    在学习C#中委托和事件时,产生一个疑问,类中定义的事件在类内部可以直接调用,而在类外部,事件却只能添加或移除委托方法 比如下面这段代码,类Customer中定义了一个委托 Order ,Customer内部可以直接调用 Order.Invoke() public class Customer { // 定义事件 public event OrderEventHandler Order; public string? name; public float? price; protected voi

  • node.js中事件触发器events的使用方法实例分析

    本文实例讲述了node.js中事件触发器events的使用方法.分享给大家供大家参考,具体如下: node.js是基于事件驱动的,通过events,我们可以方便的创建事件,并通过触发事件来调用我们自定义的监听函数. 所有能触发事件的对象都应该是 EventEmitter 类的实例,一般我们自定义一个类继承于 EventEmitter 类. 通过on()方法我们可以绑定事件与监听函数: const Events = require('events'); //自定义一个类,继承于EventEmitt

  • java中构造器内部调用构造器实例详解

    可能为一个类写了多个构造器,有时可能想在一个构造器里面调用另外一个构造器,为了减少代码的重复,可用this关键字做到这一点. public class Flower { private String string; private int age; public Flower() { // 先调用public Flower(String string, int age) this("leon", 120); // 先调用public Flower(String string, int

  • node事件循环中事件执行的顺序

    目录 事件循环 浏览器环境事件循环 node环境事件循环 六个阶段 (1) setTimeout 和 setImmediate (2) process.nextTick 练习例子 总结: 事件循环 在浏览器环境下我们的js有一套自己的事件循环,同样在node环境下也有一套类似的事件循环. 浏览器环境事件循环 首先,我们先来回顾一下在浏览器的事件循环: 总结来说: 首先会运行主线程的同步代码,每一行同步代码都会被压入执行栈,每一行异步代码会压入异步API中(如:定时器线程.ajax线程等:),在执

  • 浅谈Python中函数的定义及其调用方法

    一.函数的定义及其应用 所谓函数,就是把具有独立功能的代码块组织成为一个小模块,在需要的时候调用函数的使用包含两个步骤 1.定义函数–封装独立的功能 2.调用函数–享受封装的成果 函数的作用:在开发时,使用函数可以提高编写的效率以及代码的重用'' 函数: 函数是带名字的代码块,用于完成具体的工作 需要在程序中多次执行同一项任务时,你无需反复编写完成该任务的代码,而只需调用该任务的函数,让python运行其中的代码,你将发现,通过使用函数,程序编写,阅读,测试和修复都将更容易 1.定义函数 def

  • JS中async/await实现异步调用的方法

    async/await多个函数关联调用 async/await使得异步代码看起来像同步代码 async函数会隐式地返回一个promise,而promise的reosolve值就是函数return的值 Async/Await不需要写.then,不需要写匿名函数处理Promise的resolve值,也不需要定义多余的data变量,还避免了嵌套代码 async声明一个异步函数 await只能在async函数中使用,后面跟一个promise对象 所以在模拟异步调用函数时,函数体内返回promise as

  • 详解SpringBoot中异步请求和异步调用(看完这一篇就够了)

    一.SpringBoot中异步请求的使用 1.异步请求与同步请求 特点: 可以先释放容器分配给请求的线程与相关资源,减轻系统负担,释放了容器所分配线程的请求,其响应将被延后,可以在耗时处理完成(例如长时间的运算)时再对客户端进行响应.一句话:增加了服务器对客户端请求的吞吐量(实际生产上我们用的比较少,如果并发请求量很大的情况下,我们会通过nginx把请求负载到集群服务的各个节点上来分摊请求压力,当然还可以通过消息队列来做请求的缓冲). 2.异步请求的实现 方式一:Servlet方式实现异步请求

  • Yii Framework框架中事件和行为的区别及应用实例分析

    本文实例讲述了Yii Framework框架中事件和行为的区别及应用.分享给大家供大家参考,具体如下: 个人觉得,在 Yii 里面,最难以明白的就是事件(Event)和行为(behavior)了.这不仅仅是因为它们的概念 比较难明,关键是它们的应用场景比较难明,不知道什么时候应该使用事件和行为来开发. 关于 Yii 的事件和行为的描述,可参考 http://www.yiiframework.com/doc/api/1.1/CComponent 本文参考的文章: http://www.larryu

  • 详解JavaScript中的执行上下文及调用堆栈

    一.执行上下文是什么 代码运行是在一定的环境之中运行的,这个运行环境我们就成为执行环境,也就是执行上下文,按照执行环境不同,我们可以分为三类: 全局执行环境:代码首次执行时候的默认环境 函数执行环境:每当执行流程进入到一个函数体内部的时候 Eval执行环境:当eval函数内部的文本执行的时候 二.执行上下文栈是什么 既然是'栈',那就得符合'栈'的特性,即数据结构是先进后出.下面我们看一段代码: function cat(a){ if(a<0){ return false; } console.

随机推荐