【C#】委托、匿名方法、Lambda表达式和事件

news2024/11/16 13:57:57

【C#】委托、匿名方法、Lambda表达式和事件

委托

什么是委托?

委托和类一样,是用户自定义类型,是方法(函数)的抽象。通俗讲,委托就是 自定义类型的方法(函数)的代表。

声明委托

//<访问修饰符> delegate <函数返回类型> <自定义委托名> (函数返回参数);
//定义 返回值为null 只有1个参数 且参数为int类型 的委托
private delegate void MyDelegate(int a);
//定义 返回值为double 有2个参数 且参数为string 和 bool 类型 的委托
public delegate double MySDelegate(string a, bool b);
注意:委托可以在类里面和类外面声明。委托可以有参数,也可以无参数。返回类型可以为null,也可以为其他。

委托的实例化

委托对象必须使用new关键字来创建,且必须传入声明委托时 定义类型的方法(函数)作为注册方法。

MyDelegate myDelegate = new MyDelegate(Method1);//委托实例化

不传入注册方法会报错:
在这里插入图片描述

委托的使用

下列代码中,声明 返回一个带有string参数 返回值null 的委托,并且将Student实例对象stu1的Perform方法(函数)作为注册方法,进行实例化委托对象。

class Student
{
    public void Perform(string content)
    {
        Console.WriteLine("学生表演关于" + content + "的内容");
    }
}

class Program
{
    private delegate void PerformDelegate(string content);

    static void Main(string[] args)
    {
        Student stu1 = new Student();
        PerformDelegate performDelegate = new PerformDelegate(stu1.Perform);
        performDelegate("编写程序");//输出:学生表演关于编写程序的内容
        Console.ReadLine();
    }
}

委托的单播与多播

委托可以代表多个方法(函数),委托对象使用“=”进行赋值,此时的委托只有一个方法,称为单播。
委托对象可以使用“+=”添加相同类型方法(函数),或者使用“-=”移除委托对象中的方法(函数),这些操作会使得委托包含多个方法(函数),称为多播,又称组播。

private delegate string MethodDelegate(int a, int b);

static void Main(string[] args)
{
    MethodDelegate methodDelegate = Method1;//单播
    methodDelegate += Method2;
    methodDelegate += Method1;
    methodDelegate -= Method1;
    methodDelegate += Method2;
    methodDelegate(1, 2);
    //输出:
    //Method1 : 3
    //Method2 : 2
    //Method2 : 2
    Console.ReadLine();
    
}

private static string Method1(int a, int b)
{
    Console.WriteLine("Method1 : " + (a + b));
    return "" + (a + b);
}

private static string Method2(int a, int b)
{
    Console.WriteLine("Method2 : " + (a * b));
    return "" + (a * b);
}
注意:对于有返回值的委托,将返回最后方法执行后的返回值。

Action委托和Func委托

两个委托都是系统内置的委托类型。
Action委托:返回值为空,有0-16个参数为任何类型的方法(函数)的委托类型。
Func委托:返回一个任何类型的值,有0-16个参数为任何类型的方法(函数)的委托类型。

class Program
{
    private static void Method1(bool a, string b)
    {
        Console.WriteLine("Method1");
    }

    static void Main(string[] args)
    {
        Action<bool, string> actionDelegate = Method1;
        actionDelegate(true, "a");//输出:Method1

        Func<int, double, Program, object, string> funcDelegate = Method2;
        funcDelegate(1, 2.2f, new Program(), (object)1);//输出:Method2

        Console.ReadLine();
    }

    private static string Method2(int a, double b, Program c, object d)
    {
        Console.WriteLine("Method2");
        return "";
    }
}
Action<bool, string>是 第一个参数为bool类型,第二个参数为string类型,返回null 的委托。
Func<int, double, Program, object, string>是 第一个参数为int类型,第二个参数为double类型,第三个为Program类型,第四个为object类型,返回string类型 的委托。

匿名方法与Lambda表达式

对于不需重复编写的代码内容,通过使用匿名方法或者Lambda表达式,可以不必创建单独的方法,从而能够精简代码的编写量。

1. 匿名方法

匿名方法的语法

delegate(<函数参数>){函数体};

匿名方法的使用

Action<bool, string> actionDelegate = delegate(bool a, string b)
{
    Console.WriteLine("Method1");
};
actionDelegate(true, "a");//输出:Method1

2. Lambda表达式

Lambda表达式的语法

多个参数多条语句:(<函数参数>) => {函数体};
多个参数一条返回语句:(<函数参数>) => <返回语句>;
一个参数多条语句:<函数参数> => {函数体}
一个参数一条返回语句:<函数参数> => <返回语句>;

Lambda表达式的使用

//多个参数多条语句:(<函数参数>) => {函数体};
Func<double, bool, int> funcDelegate1 = 
(a, b) =>{

    if(b)
    {
        return (int)(a * a);
    }
    return (int)a;

};
Console.WriteLine("funcDelegate1 : " + funcDelegate1(2, true));//输出:funcDelegate1 : 4

//多个参数一条返回语句:(<函数参数>) => <返回语句>;
Func<int, bool, bool> funcDelegate2 = (a, b) => b;
Console.WriteLine("funcDelegate2 : " + funcDelegate2(2, false));//输出:funcDelegate2 : False

//一个参数多条语句:<函数参数> => {函数体}
Action<string> actionDelegate1 =  a =>
{
    string tmp = "actionDelegate1" + a;
    Console.WriteLine(tmp);
};
actionDelegate1("函数体");//输出:actionDelegate1函数体

//一个参数一条返回语句:<函数参数> => <返回语句>;
Func<float, float> funcDelegate3 = x => x * x;
Console.WriteLine("funcDelegate3 : " + funcDelegate3(8));//输出:funcDelegate3 : 64

Console.ReadLine();

事件

事件是被“限制”的委托。

声明事件

public delegate void WriteDelegate();
//<访问修饰符> event 委托名 事件名
public event WriteDelegate WriteEvent;

事件的使用

class Student
{
    private string Name { get; set; }
    public Student(string Name)
    {
        this.Name = Name;
    }
    public void StartWriting()
    {
        Console.WriteLine(Name + "开始作答");
    }
}

class Teacher
{
    public delegate void WriteDelegate();
    //<访问修饰符> event 委托名 事件名
    public event WriteDelegate WriteEvent;

    public void Begin()
    {
        WriteEvent();//引发事件
    }
}
class Program
{
    static void Main(string[] args)
    {
        Teacher teacher = new Teacher();
        Student stu1 = new Student("张三");
        Student stu2 = new Student("李四");
        Student stu3 = new Student("王五");
        Student stu4 = new Student("刘六");

        teacher.WriteEvent += stu1.StartWriting;
        teacher.WriteEvent += stu2.StartWriting;
        teacher.WriteEvent += stu3.StartWriting;
        teacher.WriteEvent += stu4.StartWriting;
        teacher.Begin();
        //输出:
        //张三开始作答
        //李四开始作答
        //王五开始作答
        //刘六开始作答
        Console.ReadLine();
    }
}

委托和事件的区别

  1. 事件不能再外部调用,而委托可以。
  2. 事件不能再外部使用“=”进行赋值,而委托可以。

因为作者精力有限,文章中难免出现一些错漏,敬请广大专家和网友批评、指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/707740.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML+CSS+JavaScript华为主页

样式&#xff1a; HTMLCSSJavaScript仿华为首页 HTML: <!DOCTYPE html> <html><head><meta charset"utf-8"><link rel"stylesheet" type"text/css" href"Homepage.css"/><script type"text/ja…

NextJs下浅尝Prisma+Sqlite+逆向生成数据模型

1.安装prisma npm install prisma/client 2.创建schema.prisma npx prisma init 执行完命令后创建文件目录如下&#xff1a; 3.配置数据库连接 generator client {provider "prisma-client-js" }datasource db {provider "sqlite" //数据库类型 这…

libevent实践07:监听服务器并管理客户端

简介 函数bufferevent_new struct bufferevent * bufferevent_new(evutil_socket_t fd,bufferevent_data_cb readcb, bufferevent_data_cb writecb,bufferevent_event_cb eventcb, void *cbarg) 参数说明&#xff1a; fd:新客户端的文件描述符 readcb&#xff1a;一个函数指…

【Redis的优化】

目录 一、Redis 高可用二、 Redis 持久化2.1、Redis 提供两种方式进行持久化2.2、RDB 持久化1. 触发条件&#xff08;1&#xff09;手动触发&#xff08;2&#xff09;自动触发 2. 执行流程3. 启动时加载 2.3、AOF 持久化1. 开启AOF2. 执行流程(1&#xff09;命令追加(append)(…

深入理解 Linux 物理内存分配全链路实现

目录 内核物理内存分配接口 物理内存分配内核源码实现 内存分配的心脏 __alloc_pages prepare_alloc_pages 内存慢速分配入口 alloc_pages_slowpath 总结 内核物理内存分配接口 在物理内存分配成功的情况下&#xff0c; alloc_pages&#xff0c;alloc_page 函数返回的都是指…

2022最常用密码公布,你的账户安全吗?

密码管理工具 NordPass 公布了 2022 年最常用密码列表&#xff0c;以及破解密码所需的时间。该研究基于对来自 30 个不同国家 / 地区的 3TB 数据库的分析。研究人员将数据分为不同的垂直领域&#xff0c;使得其能够根据国家和性别进行统计分析。今年的研究主要聚焦于文化如何影…

工业软件对于现代制造业的生产效率和质量有何影响?

工业软件在提高现代制造业的生产力和质量方面发挥着至关重要的作用。比如&#xff1a; 流程自动化&#xff1a;工业软件可以实现各种制造流程的自动化&#xff0c;消除手动任务并减少人为错误。自动化通过简化操作、缩短周期时间和提高整体效率来提高生产力。它还可以最大限度地…

vue3和element plus踩坑

1.有说vue版本有两个&#xff0c;但检查之后发现只有一个&#xff0c;且为vue3的版本 2.也有说是因为命名的问题&#xff0c;组件名和页面名一致 最后发现是因为 在main.js里面引入element plus 使用这种use方式会报错&#xff0c;虽然也不知道为什么 import { createApp } …

《计算机系统与网络安全》第十一章 入侵检测与防御技术

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

Dell-Precision5520 电脑 Hackintosh 黑苹果efi引导文件

原文来源于黑果魏叔官网&#xff0c;转载需注明出处。&#xff08;下载请直接百度黑果魏叔&#xff09; 硬件配置 硬件型号驱动情况 主板Dell-Precision5520 处理器Intel Core i7-7820HQ已驱动 内存Micron 2400MHz DDR4 16GB x2已驱动 硬盘Samsung 970EVO 512GB已驱动 显…

Java中volatile的作用和原理

用法 volatile 是 Java 中的关键字&#xff0c;直接修饰成员变量&#xff0c;不能和 final 关键字同时使用。 private volatile boolean flag false;作用 当一个变量被声明为volatile时&#xff0c;它可以确保以下两点&#xff1a; 保证可见性&#xff1a;当一个线程修改了…

三维天地助力高校实验室数字化智能决策分析

近年来&#xff0c;随着检验检测行业技术的不断发展&#xff0c;高校实验室管理的复杂程度也在不断提高。由于传统的检测实验室日常工作任务繁重、费时费力&#xff0c;存在数据或信息的手动录入、人工计算&#xff0c;纸质文档资料的长期保存&#xff0c;数据快速汇总困难等诸…

大数据面试题:Kafka的Message包括哪些信息

面试题来源&#xff1a; 《大数据面试题 V4.0》 大数据面试题V3.0&#xff0c;523道题&#xff0c;679页&#xff0c;46w字 参考答案&#xff1a; 一个 Kafka 的 Message 由一个固定长度的 header 和一个变长的消息体 body 组成&#xff0c;header 部分由一个字节的 magic&…

Android 12 LED 定制灯效开发小结

文章目录 背景&#xff1a;Android 10 的设备上测试正常Android 12 中目前出现无法闪烁的问题电量变化广播监听总结参考 背景&#xff1a; 在定制的Android 10系统中&#xff0c;通过修改 Framwork 层的代码后&#xff0c;调用标准的接口后&#xff0c;能实现 LED 灯的闪烁灯效…

抖音旋转验证码分析

旋转验证码类型challenge_code为99996&#xff0c; 拿到的旋转验证码通常都是如下&#xff1a; 待旋转的图片&#xff1a; 旋转的背景图&#xff1a; 加密分析过程 可以参考&#xff1a;https://blog.csdn.net/weixin_38819889/article/details/129727564 旋转的难点在于如何…

英国 Tortoise Media发布2023年全球AI指数排名;美团宣布完成收购光年之外

&#x1f989; AI新闻 &#x1f680; 美团宣布完成收购光年之外&#xff0c;加强人工智能竞争力 摘要&#xff1a;美团在公告中宣布于2023年6月29日盘后收购光年之外的全部权益&#xff0c;以加强其在快速增长的人工智能行业中的竞争力。光年之外是中国领先的通用人工智能创新…

【ISO26262】汽车功能安全第一部分:术语

【tommi_wei@163.com】 故障响应时间 fault reaction time 从故障(2.42) 探测到进入安全状态(2.102) 的时间间隔。 故障容错时间间隔 fault tolerant time interval 在危害事件(2.59) 发生前, 系统(2.129) 中一个或多个故障(2.42) 可存在的时间间隔。 功能安全 functio…

C语言之网络高级编程笔记

基于Webserver的工业数据采集项目 html cgi Modbus协议 (应用层) 工具&#xff1a;Modus Slave/Poll wireshark Postman 一、Modbus起源 1.起源&#xff1a; Modbus由Modicon公司于1979年开发&#xff0c;是一种工业现场总线协议标准。 Modbus通信协议具有多个变种&#xf…

【Matlab】神经网络遗传算法函数极值寻优——非线性函数求极值

目前关于神经网络遗传算法函数极值寻优——非线性函数求极值的博客资源已经不少了&#xff0c;我看了下来源&#xff0c;最初的应该是来自于Matlab中文论坛&#xff0c;论坛出版的《MATLAB神经网络30个案例分析》第4章就是《神经网络遗传算法函数极值寻优——非线性函数极值寻优…

考研算法35天:三元组的最小距离 【双指针,滑动窗口,多路归并】

算法详解 多路归并;多路归并算法从理论到应用&#xff08;易懂&#xff09;_留恋单行路的博客-CSDN博客 多路归并就是将多个已经归并排序排好序的数组再进行排序(不一定是通过归并排序)。 算法题目 这道题就是一般做法是先通过排序将三个数组排好然后再进行三指针求最小。但…