图解C#高级教程(一):委托

什么是委托

可以认为委托是持有一个或多个方法的对象。但它与对象不同,因为委托可以被执行。当执行委托时,委托会执行它所“持有”的方法。先看一个完整的使用示例。

// See https://aka.ms/new-console-template for more informationdelegate void MyDel(int value);  // 声明委托类型class Program
{void PrintLow(int value){Console.WriteLine("{0} - Low value", value);}void PrintHigh(int value){Console.WriteLine("{0} - High value", value);}static void Main(string[] args){Program p = new Program();MyDel del;  // 声明委托变量Random rand = new Random();int randomValue = rand.Next(1, 101);del = randomValue < 50 ? p.PrintLow : p.PrintHigh;  // 选择调用哪个方法del(randomValue);  // 调用委托方法}
}

如果生成的随机数 randomValue 小于50,则 del 引用的是 p.PrintLow;否则,del 引用的是 p.PrintHigh

委托概述

下图是使用类和委托的对比:
在这里插入图片描述

可以把 delegate 看成一个包含有序方法列表的对象,这些方法具有相同的签名和返回类型。如下图所示:
在这里插入图片描述

委托的几点说明:

  • 方法的列表称为调用列表;

  • 委托保存的方法可以来自任何类或者结构,只要它们在委托的返回类型和委托的签名(包括ref和out修饰符)上保持一致;

  • 调用列表中的方法可以是实例方法,和静态方法;

  • 执行委托时,会按照方法的添加顺序执行调用列表。

声明委托类型

在这里插入图片描述

创建委托对象

委托是引用类型,因此初始化委托变量需要创建一个对象。有两种方式创建委托对象:

  • 使用 new 运算符:

    class Obj
    {void MyM1(int value) {}static void Other(int value) {}}
    delegate void MyDel(int value);MyDel del1, del2;Obj obj = new Obj();
    del1 = new MyDel(obj.MyM1);  // 使用一个对象的方法
    del2 = new MyDel(Obj.Other);  // 使用静态方法创建委托对象
    
  • 省略 new 运算符:

    MyDel del1, del2;
    del1 = obj.MyM1;  // 使用一个对象的方法
    del2 = Obj.Other;  // 使用静态方法创建委托对象
    

    当为委托变量赋值时,除了为委托分配内存,创建委托对象还会把第一个方法放入委托的调用列表。

    当然,我们还可以在声明委托变量时初始化委托变量。

    MyDel del1 = obj.MyM1;
    

    当我们为同一个委托变量赋值另外一个委托对象时,之前的委托对象就会被垃圾回收器回收。

    MyDel delVar;
    delVar = myInstObj.MyM1;
    ...
    delVar = SClass.OtherM2;
    

在这里插入图片描述

组合委托

可以将两个同类型的委托变量进行 + 操作,赋值给另外一个同类型的新变量,完成委托的组合:

MyDel delA = myInstObj.MyM1;
MyDel delB = SClass.OtherM2;MyDel delC = delA + delB;

在这里插入图片描述

为委托添加或者删除方法

委托可以持有多个方法, 通过使用运算符 +=-= 可以为委托添加或者删除方法。

MyDel del = inst.MyM1;
del += SCl.m3;
del += X.Act;

在这里插入图片描述
从委托移除方法:

del -= SCl.m3;

在这里插入图片描述

移除委托时需要注意以下事项:

  • 如果委托的调用列表中存在多个实例,-= 运算符将从列表的最后开始搜索,并移除第一个与方法匹配的实例;
  • 当要删除的方法在调用列表不存在时,什么也不会发生;
  • 试图调用空委托将会导致异常,因此执行委托之前有必要进行 null 判空。

调用委托

调用委托的方式与调用方法一样。用于调用委托的参数将会传递给调用列表当中的每一个方法(除非有输出参数)。

MyDel delVar = inst.MyM1;
delVar += SCl.m3;
delVar += X.Act;
...
delVar(55);

在这里插入图片描述

下面是一个完整的示例:

delegate void PrintFunction();class Test
{public void Print1(){Console.WriteLine("Print1 -- instance method");}public static void Print2(){Console.WriteLine("Print2 -- static method");}}class Program
{static void Main(){Test t = new Test();PrintFunction pf;
// 实例方法pf = t.Print1;// 给委托增加3个另外的方法pf += Test.Print2;pf += t.Print1;pf += Test.Print2;   // 现在委托含有4个方法if (null != pf){pf();}else{Console.WriteLine("委托为空");}}
}

输出如下:

Print1 -- instance method
Print2 -- static method
Print1 -- instance method
Print2 -- static method

调用带引用参数的委托

如果委托有引用参数,在调用委托列表中的下一个方法时,参数的新值会传给下一个方法。

delegate void MyDel(ref int x);class MyClass
{public void Add2(ref int x) { x += 2; }public void Add3(ref int x) { x += 3; }static void Main(){MyClass mc = new MyClass();MyDel del = mc.Add2;del += mc.Add3;del += mc.Add2;int x = 5;del(ref x);Console.WriteLine("Value: {0}", x);}
}

输出如下:

Value: 12

在这里插入图片描述

Lambda 表达式

C# 当中的 Lambda 表达式是一种简洁的方式来表示匿名方法。通常用于简化代码,尤其是在与 LINQ、委托或事件等相关的场景中。(LINQ 和 事件会在后面相关文章中讲到)。

语法:

(parameters) => expression
  • parameters:代表输入参数。如果只有一个参数,可以省略()
  • =>:称为 lambda 操作符,表示从参数到表达式或代码块的映射。
  • expression:返回的表达式。如果有多条语句,可以使用代码块{}。

Lambda 表达式的常见使用场景

  1. 委托与 Lambda 表达式
delegate void MyDel(int x);MyDel del = x => x *2;

用于 Func<T>委托:

using System;class Program
{static void Main(){// Func 委托,接受两个整数参数,返回它们的和Func<int, int, int> add = (a, b) => a + b;int result = add(3, 4);Console.WriteLine(result);  // 输出 7}
}

Func 是 C# 中一个常用的泛型委托类型,在 C# 3.0 中引入,专门用于表示带有返回值的方法。在使用时,Func<T> 委托的最后一个泛型参数是返回值类型(必须有),前面的泛型参数是输入参数类型(可以没有输入参数)。

  1. Lambda 表达式与 LINQ 查询

    using System;
    using System.Linq;
    using System.Collections.Generic;class Program
    {static void Main(){List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };// 使用 Lambda 表达式筛选出大于 3 的数var result = numbers.Where(n => n > 3).ToList();foreach (var number in result){Console.WriteLine(number);  // 输出 4, 5, 6}}
    }
    
  2. 用于事件处理

    using System;class Program
    {static void Main(){Action<string> messagePrinter = msg => Console.WriteLine(msg);messagePrinter("Hello, Lambda!");  // 输出 "Hello, Lambda!"}
    }

委托的使用场景

委托的主要使用场景如下:

  • 事件处理。
  • 回调函数。

以上两个使用场景的具体例子会在后面文章介绍到。

小结:本章主要介绍了 C# 当中委托和 Lambda 的概念、用法。

各位道友,码字不易,如有收获,记得一键三连啊。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hello-Java-Sec靶场搭建

安装环境&#xff1a;宝塔Linux面板 1.将靶场克隆到本地 git clone https://github.com/j3ers3/Hello-Java-Sec 2.安装maven yum install maven &#xff08;kali&#xff1a;apt install maven&#xff09; 3.安装成功后 mvn -v验证⼀下 4. 配置数据库连接&#xff0c;数据…

【AI学习】DDPM 无条件去噪扩散概率模型实现(pytorch)

这里主要使用pytorch实现基本的无条件去噪扩散模型&#xff0c;理论上面的推导这里不重点介绍。 原文理论参考&#xff1a; 前向和反向过程示意图 前向过程和后向过程 扩散过程包括正向过程和反向过程。前向过程是基于噪声调度的预定马尔可夫链。噪声表是一组方差 &#xff0…

YOLOv11训练自己的数据集(从代码下载到实例测试)

文章目录 前言一、YOLOv11模型结构图二、环境搭建三、构建数据集四、修改配置文件①数据集文件配置②模型文件配置③训练文件配置 四、模型训练和测试模型训练模型验证模型推理 总结 前言 提示&#xff1a;本文是YOLOv11训练自己数据集的记录教程&#xff0c;需要大家在本地已…

心觉:如何重塑高效学习的潜意识(5)终结篇

Hi&#xff0c;我是心觉&#xff0c;与你一起玩转潜意识、脑波音乐和吸引力法则&#xff0c;轻松掌控自己的人生&#xff01; 挑战每日一省写作184/1000天 上篇文章讲了如何发挥边学边用的威力及其底层逻辑 到此为止&#xff0c;我们已经系统地把“系统化学习”和“边学边用…

【教程】57帧! Mac电脑流畅运行黑神话悟空

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 1、先安装CrossOver。网上有许多和谐版&#xff0c;可自行搜索。&#xff08;pd虚拟机里运行黑神话估计够呛的&#xff09; 2、运行CrossOver&#xf…

常州威雅学校:欢迎探访校园,共赴全人教育之旅!

自2012年创校起&#xff0c;我们践行着“每一个孩子都卓越”的全人教育理念&#xff0c;见证了常州威雅发展至今天的方兴未艾。在岁月不居&#xff0c;时节如流间&#xff0c;我们用点点滴滴的耕耘&#xff0c;为学生的成长穿针引线&#xff0c;也在学校建设中精益求精。 一百次…

理解 Vue 的 setup 应用程序钩子

title: 理解 Vue 的 setup 应用程序钩子 date: 2024/9/30 updated: 2024/9/30 author: cmdragon excerpt: 摘要:本文详细介绍了Vue 3中setup函数的应用,包括其概念、特性、使用方法及重要性。setup函数作为组合API的核心,在组件实例化前被调用,用于设置响应式状态、计算…

解决 Failed to connect to 127.0.0.1 port XXXX: Connection refused问题

查看自己的代理&#xff0c;如果有设置&#xff0c;取消即可。注意https还是http&#xff0c;或者都取消算了 git config --global http.proxy git config --global --unset http.proxygit config --global https.proxy git config --global --unset https.proxy注意如果有人在…

APISIX 联动雷池 WAF 实现 Web 安全防护

Apache APISIX 是一个动态、实时、高性能的云原生 API 网关&#xff0c;提供了负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。 雷池是由长亭科技开发的 WAF 系统&#xff0c;提供对 HTTP 请求的安全请求&#xff0c;提供完整的 API 管理和…

纯软件小白 学习DDR5

问题 1.你知道当你打开游戏加载存档时候计算机是在做什么吗&#xff1f; 由于你的CPU只有在数据被加载到DRAM的时候才可以工作&#xff0c;所以当你需要用数据的时候&#xff0c;数据会从SSD复制到DRAM这一过程需要时间&#xff0c;所以会有加载&#xff08;所有3D模型、纹理…

Tensorflow2.0

Tensorflow2.0 有深度学习基础的建议直接看class3 class1 介绍 人工智能3学派 行为主义:基于控制论&#xff0c;构建感知-动作控制系统。(控制论&#xff0c;如平衡、行走、避障等自适应控制系统) 符号主义:基于算数逻辑表达式&#xff0c;求解问题时先把问题描述为表达式…

完成UI界面的绘制

绘制UI 接上文&#xff0c;在Order90Canvas下创建Image子物体&#xff0c;图片资源ui_fish_lv1&#xff0c;设置锚点&#xff08;CountdownPanelImg同理&#xff09;&#xff0c;命名为LvPanelImg,创建Text子物体&#xff0c;边框宽高各50&#xff0c; &#xff0c;重名为LvT…

【2025】基于Spring Boot的智慧农业小程序(源码+文档+调试+答疑)

文章目录 一、***-项目介绍二、***-开发环境三、***-系统展示四、***-代码展示五、***-项目文档展示六、***-项目总结 大家可以帮忙点赞、收藏、关注、评论啦 &#x1f447;&#x1f3fb; 一、***-项目介绍 当今社会已经步入了科学技术进步和经济社会快速发展的新时期&#x…

如何使用 Python 读取数据量庞大的 excel 文件

使用 pandas.read_excel 读取大文件时&#xff0c;的确会遇到性能瓶颈&#xff0c;特别是对于10万行20列这种规模的 .xlsx 文件&#xff0c;常规的 pandas 方法可能会比较慢。 要提高读取速度&#xff0c;关键是找到更高效的方式处理 Excel 文件&#xff0c;特别是在 Python 的…

Docker安装consul + go使用consul + consul知识

1. 什么是服务注册和发现 假如这个产品已经在线上运行&#xff0c;有一天运营想搞一场促销活动&#xff0c;那么我们相对应的【用户服务】可能就要新开启三个微服务实例来支撑这场促销活动。而与此同时&#xff0c;作为苦逼程序员的你就只有手动去 API gateway 中添加新增的这…

MongoDB的安装与增删改查基本操作

MongoDB是一种非关系型数据库&#xff0c;是NoSQL语言&#xff0c;但是又是最接近关系型数据库的。内部存储不是表结构&#xff0c;但是可以对数据进行表结构的操作。 一、安装 在官网&#xff1a;Download MongoDB Community Server | MongoDB下载系统对应的版本进行安装即可…

掌握CMD命令:轻松切换IP地址

在日常的网络管理与维护中&#xff0c;切换IP地址是一项常见且重要的操作。无论是为了测试网络配置、访问特定资源&#xff0c;还是解决IP冲突问题&#xff0c;掌握如何在命令行界面&#xff08;CMD&#xff09;中切换IP地址都是每个网络管理员或高级用户的必备技能。本文将详细…

asp.net mvc core 路由约束,数据标记DataTokens

》从0自己搭建MVC 》用 asp.net Core web 应用 空web 应用程序 需要配置 mvc服务 、mvc路由 新建 Controller 、Models、Views 》》》core 6 之前版本 vs2022 asp.net Core Web 应用&#xff08;模型-视图-控制器&#xff09; 不需要配置 就是mvc框架 asp.net Core web 应…

怎么查看网站是否被谷歌收录,查看网站是否被搜索引擎收录5个方法与步骤

要查看网站是否被谷歌&#xff08;Google&#xff09;或其他搜索引擎收录&#xff0c;是网站管理和SEO&#xff08;搜索引擎优化&#xff09;中的一个重要环节。以下是查看网站是否被搜索引擎收录5个方法与步骤&#xff0c;帮助您确认网站是否被搜索引擎成功索引&#xff1a; …

丹摩智算(damodel)部署stable diffusion实验

名词解释&#xff1a; 丹摩智算&#xff08;damodel&#xff09;&#xff1a;是一款带有RTX4090&#xff0c;Tesla-P40等显卡的公有云服务器。 stable diffusion&#xff1a;是一个大模型&#xff0c;可支持文生图&#xff0c;图生图&#xff0c;文生视频等功能 一.实验目标 …