C#中的委托(Delegate)和事件 (Event)详解与使用范例

2023-05-16

一.委托(Delegate)

1.委托(Delegate)简介

最近天气晴雨不定,你因为害怕打游戏时忘记在下雨时收衣服或者在天晴时把衣服挂出去,于是你委托好友小明在天气发生变化时打电话通知你,这就是一种委托.

下面是这种委托的实例代码

//定义一个继承自Delegate类的子类小明,这之后小明就具备被委托的属性
//public为公开,void为返回类型,XiaoMing为类名,(string msg)为传递给注册的方法的参数
public delegate void XiaoMing(string msg);
class Me
{
    //public代表聆听小明的信号是公开的方法,以便小明访问
    //static是为了固定ListenToXiaoMing在内存中的入口以便小明能够找到该方法的入口
    public static void ListenToXiaoMing(string msg)
    {
        if(msg == "Rain")
        {
            Console.WriteLine("下雨了!小明收衣服了!");
        }
        else if(msg == "Sunny")
        {
            Console.WriteLine("天晴了!小明晒衣服了!");

        }
    }
}


class Program
{
    static void Main(string[] args)
    {
        //初始化一个XiaoMing类的实体xiaoMing
        //将我的ListenToXiaoMing注册在xiaoMing上
        //相当于我与小明约定下雨后小明就通知我做出行动(调用ListenToXiaoMing)
        XiaoMing xiaoMing = Me.ListenToXiaoMing;



        //假设今天下雨
        string weather = "Rain";
        
        //小明观察天气
        //将weather参数传递给Me.ListenToXiaoMing方法
        xiaoMing.Invoke(weather);

    }
}

以上代码的输出为

下雨了!小明收衣服了!

值得一提的是,如下代码为创建一个继承自Delegate类的名为XiaoMing的子类,该子类实例只接收void类型方法并且参数类型为(string)的注册,如:void foo(string test){}

public delegate void XiaoMing(string msg);

2.组播委托

你感觉小明的提醒十分靠谱,于是将这件事告诉了同样喜欢玩游戏的小刚,于是小刚也决定请小明在天气发生变化时提醒他,这就是组播委托.

当执行delegate.Invoke()时,将会执行所有注册在该delegate上的方法

以下是这种委托的代码:

public delegate void XiaoMing(string msg);


//你的类
class Me
{
    //public代表聆听小明的信号是公开的方法,以便小明访问
    //static是为了固定ListenToXiaoMing在内存中的入口以便小明能够找到该方法的入口
    public static void MeListenToXiaoMing(string msg)
    {
        if(msg == "Rain")
        {
            Console.WriteLine("下雨了!小明收衣服了!");
        }
        else if(msg == "Sunny")
        {
            Console.WriteLine("天晴了!小明晒衣服了!");

        }
    }
}


//小刚的类
class XiaoGang
{
    
    public static void XiaoGangListenToXiaoMing(string msg)
    {
        if (msg == "Rain")
        {
            Console.WriteLine("下雨了!小刚收衣服了!");
        }
        else if (msg == "Sunny")
        {
            Console.WriteLine("天晴了!小刚晒衣服了!");

        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        //初始化一个XiaoMing类的实体xiaoMing
        //将我的ListenToXiaoMing注册在xiaoMing上
        //相当于我与小明约定下雨后小明就通知我做出行动(调用ListenToXiaoMing)
        XiaoMing xiaoMing = Me.MeListenToXiaoMing;

        //小刚也将自己的XiaoGangListenToXiaoMing注册到被委托人小明身上
        xiaoMing += XiaoGang.XiaoGangListenToXiaoMing;



        //假设今天下雨
        string weather = "Rain";

        //小明观察天气
        //将weather参数传递给Me.ListenToXiaoMing方法
        //和XiaoGang.XiaoGangListenToXiaoMing方法
        xiaoMing.Invoke(weather);

    }
}

运行结果为

下雨了!小明收衣服了!
下雨了!小刚收衣服了!

注意事项:

在使用Delegate子类时,需要用如下代码进行初始化

//方法一 
XiaoMing xiaoMing; 
xiaoMing=Me.MeListenToXiaoMing;
//方法二
XiaoMing xiaoMing=Me.MeListenToXiaoMing;

//错误示范
XiaoMing xiaoMing;
xiaoMing+=Me.MeListenToXiaoMing;

3.事件(event)与委托配合

当你和小刚为小明的靠谱感叹时,天气变化无常的季节结束了,你们不再需要小明通知你们收放衣服了.

你们又有了新的需求----你喜欢在阴天运动,但是小刚喜欢在晴天运动,于是你们请小明吃了一顿饭,请求他在阴天通知你运动,在晴天通知小刚运动,这样的话你们就不用在收到阴天和晴天的消息时花费精力自行判断要不要运动了.

以下是这次委托的代码,小明将会根据不同情况通知不同的人

//好朋友小明类
class XiaoMing
{
    //定义一个继承自Delegate类的委托子类,就像是呼叫是人们通讯的方法
    //而小明的呼叫是继承自呼叫的子类
    public delegate void CallTFirends();


    //以下是事件,是一个用于触发不同委托的字段
    //这是委托你去运动的字段
    public  event CallTFirends CallMe;

    //这是委托小刚去运动的字段
    public event CallTFirends CallXiaoGang;
    
    
    
    //好心的小明用下面的方法时时关注天气
    public void LookForWeather(string weather)
    {
        if (weather == "Cloudy")
        {
            //与下方的CallXiaoMing?.Invoke();具有相同功能
            //即防止小明小刚还没通知喜欢哪种运动天气时进行提醒
            //防止在event还没注册时就被调用
            if (CallMe != null)
            {
                CallMe.Invoke();
            }
        }
        else if(weather == "Sunny")
        {
            CallXiaoGang?.Invoke();
        }

    }

}


//你的类
class Me
{
    //你收到小明的信号会调用以下方法去运动
    public static void MeListenToXiaoMing()
    {
       Console.WriteLine("小明运动啦!");
    }
}


//小刚的类
class XiaoGang
{

    //小刚收到小明的信号会调用以下方法去运动
    public static void XiaoGangListenToXiaoMing()
    {
        Console.WriteLine("小刚运动啦!");
    }
}

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

        XiaoMing xiaoMing = new XiaoMing();
        //天气为阴天
        string weather = "Cloudy";

        //你注册了callMe的事件,意味通知小明在阴天通知你去运动
        xiaoMing.CallMe += Me.MeListenToXiaoMing;
        //小刚注册了XiaoGang.XiaoGangListenToXiaoMing事件,意味通知小明在晴天通知小刚去运动
        xiaoMing.CallXiaoGang += XiaoGang.XiaoGangListenToXiaoMing;

        //小明观察天气并且提醒对应的人去运动
        xiaoMing.LookForWeather(weather);
       

    }
}

运行结果为

小明运动啦!

细节提示:

1.事件只能在声明它的类中被触发(即例子中在XiaoMing类种才能触发),在声明它的类之外只能订阅和取消订阅。

2.事件的一大作用是方便由声明Delegate的类集中管理而不用每个类自行判断传输过来的信号,如你和小刚不用自行判断传来的天气适合做什么只需要在收到消息后去运动即可.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#中的委托(Delegate)和事件 (Event)详解与使用范例 的相关文章

随机推荐

  • 小国王——状压DP

    在 n n 的棋盘上放 k 个国王 xff0c 国王可攻击相邻的 8 个格子 xff0c 求使它们无法互相攻击的方案总数 输入格式 共一行 xff0c 包含两个整数 n 和 k 输出格式 共一行 xff0c 表示方案总数 xff0c 若不能
  • 小国王(目标状态优化版)—— 状态压缩DP

    在 n n 的棋盘上放 k 个国王 xff0c 国王可攻击相邻的 8 个格子 xff0c 求使它们无法互相攻击的方案总数 输入格式 共一行 xff0c 包含两个整数 n 和 k 输出格式 共一行 xff0c 表示方案总数 xff0c 若不能
  • 炮兵阵地——状态压缩DP

    司令部的将军们打算在 N MN M 的网格地图上部署他们的炮兵部队 一个 N MN M 的地图由 NN 行 MM 列组成 xff0c 地图的每一格可能是山地 xff08 用 H 表示 xff09 xff0c 也可能是平原 xff08 用 P
  • hadoop项目实战——奥运会数据分析

    大三学期项目 hadoop MapReduce 奥运会数据分析结果 xff1a 有没需要详细实现方法的小伙伴呀 xff1f 可以在评论区评论一下 如果人多 xff0c 那么后续会详细更新实现方法
  • RT-Thread 内核线程切换原理

    1 背景 本文章主要说明 rtthread 内核线程是如何切换的 xff0c 初学者刚从裸机开发接触 RTOS 时难免会有些不适应 xff0c 明白这部分原理之后就会对 RTOS 有更深的理解 在学习内核线程切换原理之前需要有以下基础知识铺
  • 【多线程】C/C++语言中多线程和简单例子

    目录 前言 一 pthread两种状态joinable和unjoinable 二 thread join 方法存在的必要性 三 为什么要多线程 xff1a 问题 xff1a 简单的多线程编程 线程的数据处理 四 实例代码 C 43 43 C
  • 单片机开发之裸机也能 “多任务”?

    单片机开发之裸机也能 多任务 xff1f 1 背景 对于一些简单的单片机项目 xff0c 没必要非得跑RTOS xff0c 因此 xff0c 很多项目都是在 裸奔 指纯循环加上中断的机制 所以 xff0c 开发出一套好用的裸机框架是非常有必
  • vscode如何运行C++程序

    首先说一下vscode是一个支持跨平台的轻量级编辑器 1 安装c c 43 43 编译器 Linux系统一般都自带gcc和g 43 43 xff0c 但对于Windows系统而言就需要安装Mingw w64来获得编译器 步骤如下 xff1a
  • TX2 安装显卡驱动

    1 官网查询驱动版本 官方 GeForce 驱动程序 NVIDIA 这个版本gcc不合适 xff0c 换了下一个 又换了一个版本 xff0c 依旧有gcc版本问题 但查了一些资料 xff0c 对照一些版本 xff0c 觉得可能gcc冲突并不
  • 04 ROS Client-Service-Server实例

    零 Service机制 Client与Server向ROS MASTER注册MASTER根据Client订阅的信息 xff0c 查阅注册表中是否有提供对应Service的ServerClient收到Server的TCP通信地址Client用
  • ROS2教程 02 功能包

    一 检查别人的功能包依赖 当移植别人的功能包到本机时 xff0c 需要在工作空间目录下检查功能包依赖是否健全 rosdepc span class token function install span i from path src ro
  • 从零开始学习无人机 00 硬件配置

    遥控器 型号 乐迪Radiolink AT9S Pro 固件更新 对遥控器固件作更新 乐迪Radiolink AT9S Pro 固件更新 光流传感器 型号 思动智能ThoneFlow 3901U 开发文档 Pmw3901光流传感器PX4开发
  • 树莓派ubuntu镜像备份详细教程

    1 获取镜像 将配置好环境的树莓派sd卡放入读卡器将读卡器插入电脑在Windows操作系统上使用软件win32diskimager获取镜像将镜像保存到Linux操作系统上某个位置 xff0c 例如ubuntu22 04 2 减小镜像体积 安
  • Java开发必须会的技能!kafka集群3个节点挂掉一个

    Maven权威指南 首先 xff0c 本书适合所有Java程序员阅读 由于自动化构建 依赖管理等问题并不只存在于Java世界 xff0c 因此非Java程序员也能够从该书中获益 无论你是从未接触过Maven 还是已经用了Maven很长时间
  • 大厂首发!阿里面试官跟我死磕MySQL,Java岗

    前言 蓦然回首自己做开发已经十年了 xff0c 这十年中我获得了很多 xff0c 技术能力 培训 出国 大公司的经历 xff0c 还有很多很好的朋友 但再仔细一想 xff0c 这十年中我至少浪费了五年时间 xff0c 这五年可以足够让自己成
  • C语言和数据结构与算法(99)

    1 预处理和关键字 22道 1 1 宏定义是在编译的哪个阶段处理的 xff1f 答案 xff1a 在编译的预处理阶段 xff0c 被处理的 编译预处理包括 xff1a 宏替换 文件包含 条件编译 其他预处理指令 1 2 写一个 标准 宏定义
  • 【MYSQL】同时查询两个表并将结果合并到一起

    目录 从两个表中查不同字段并拼接到一起 xff08 从两个表中查的字段不一样 xff09 将两个表结果合并 xff08 从两个表中查的字段一样 xff09 SQL多表合并UNION ALL和UNION 从两个表中查不同字段并拼接到一起 xf
  • C语言和数据结构与算法(99)

    2 数据类型 xff08 22道 xff09 2 1 用变量a给出下面的定义 xff08 1 xff09 一个整型数 xff1a int a xff08 2 xff09 一个指向整型数的指针 xff08 一重指针 xff09 xff1a i
  • 详解STL---vector

    目录 1 vector的介绍及应用 1 1vector的介绍 1 2vector的使用 1 2 1 vector的定义 1 2 2 vector iterator 的使用 1 2 3 vector 空间增长问题 1 2 4 vector 的
  • C#中的委托(Delegate)和事件 (Event)详解与使用范例

    一 委托 Delegate 1 委托 Delegate 简介 最近天气晴雨不定 你因为害怕打游戏时忘记在下雨时收衣服或者在天晴时把衣服挂出去 于是你委托好友小明在天气发生变化时打电话通知你 这就是一种委托 下面是这种委托的实例代码 定义一个