【.NET Core】委托(Delegate)应用详解

【.NET Core】委托(Delegate)应用详解

文章目录

  • 【.NET Core】委托(Delegate)应用详解
    • 一、概述
    • 二、委托(Delegate)定义
    • 三、基础委托(Delegate) - 无返回值委托
    • 四、基础委托(Delegate) - 有返回值委托
    • 五、MulticastDelegate 多播委托
    • 六、匿名方法
    • 七、匿名委托之Action
    • 八、匿名委托之Func
    • 九、委托总结
    • 十、参考资料

一、概述

委托(Delegate)是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托(Delegate)类似于C或C++中函数指针。委托是将方法调用者和目标方法动态关联起来,委托是一个类,实质上是一个类,可以通过委托隐藏方法,虽然委托定义方法的参数及其返回值,但是它并不是和方法一个层级的。

委托(Delegate)可以将方法当作另一个方法的参数来进行传递,这种方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

二、委托(Delegate)定义

声明一个委托的语法如下:

deletgate <return type> <delegate-name> <parameter list>
  • delegate 定义委托关键字
  • return type 返回类型 (与方法返回值相同)
  • delegate-name 委托的命名
  • parameter list 参数列表 (与方法入参相同)

声明委托步骤

  1. 声明一个delegate对象,它应当与要传统的方法具有相同的参数和返回值类型。
  2. 创建delegate对象,new Delegate传入参数
  3. 通过delegate调用方法,并返回值。

代码演示

delegate int DegaAdd(int a,int b,int c);
public int add(int a,int b,int c){return a+b+c;
}
public static void Main(String[] args){DegaAdd degaAdd=new DegaAdd(add);int respVal =degaAdd(2,3,4);Console.WriteLine(respVal);
}

三、基础委托(Delegate) - 无返回值委托

public class Program 
{public delegate void DelegateNoReturn(string param1, string param2);public static void NoReturn(string param1, string param2) {Console.WriteLine(param1+" "+param2+".");}public static void Main(string[] args) {DelegateNoReturn delegateNoReturn;delegateNoReturn = NoReturn;delegateNoReturn("Hello", "Delegate");}
}

四、基础委托(Delegate) - 有返回值委托

public class Program 
{public delegate void DelegateNoReturn(string param1, string param2);public delegate string DelegateHaveReturn(string param1, string param2);public static void NoReturn(string param1, string param2) {Console.WriteLine(param1+" "+param2+".");}public static string HaveReturn(string param1, string param2) {return ("有参数Delegate:"+param1 + " " + param2 + ".");}public static void Main(string[] args){DelegateHaveReturn delegateHaveReturn;delegateHaveReturn = HaveReturn;string response = delegateHaveReturn("Hello", "Delegate");Console.WriteLine(response);}
}

五、MulticastDelegate 多播委托

多播委托(MulticastDelegate)是指在一个委托中注册多个方法,在注册方法时可以在委托中使用加号运算符或者减号运算符来实现添加或撤销方法。

创建一个方法集合类

public class DelegateMethod
{public static void Method1(){Console.WriteLine("委托方法一.");}public void Method2() {Console.WriteLine("委托方法二.");}public void Method3(){Console.WriteLine("委托方法三.");}
}

创建一个多播委托

public class Program 
{public delegate void OrderDelegate();public static void Main(string[] args) {OrderDelegate orderDelegate = new OrderDelegate(DelegateMethod.Method1);orderDelegate += new DelegateMethod().Method2;orderDelegate += new DelegateMethod().Method3;orderDelegate();}
}

输出

委托方法一.
委托方法二.
委托方法三.

六、匿名方法

匿名方法(Anonymous methods)提供了一种传递代码块作为委托参数的技术。匿名方法是没有名称只有主体的方法。

在匿名方法中您不需要指定返回类型,它是从方法体内的return语句推断的。

.net 3.0以前的版本,匿名方法是通过使用delegate关键字创建委托实例来声明的

delegate void ValueChange(int n);
...
ValueChange vchange=delegate(int x)
{Console.WriteLine("Anonymous Method:{0}",x);
}

对于高于C#3.0 的版本中,可以用Lambda表达式进行取代匿名方法,并用Lambda表达式作为编写内联代码的首选方式,因为它更简洁。

button1.Click+=delegate(Object o,EventArgs e)
{Console.WriteLine("Anonymous Method:");
}

七、匿名委托之Action

Action是.NET Framework内置的泛型委托,可以使用Action委托以参数形式传递方法,而不用显示声明自定义的委托。封装的方法必须与此委托定义的方法签名相对应。也就是说,封装的方法必须具有一个通过值传递给它的参数,并并且不能有返回值。

Action的特点:

  1. 参数个数0~16
  2. 没有返回值
public class ActionDemo
{public void Operate() {Action action1 = new Action(Method1);Action<int, int> action2 = new Action<int, int>(Method2);action1();action2(1, 2);Action<int ,string,string> action3= delegate (int i1 ,string i2,string s){Console.WriteLine($"这里是三个参数的Action委托,参数1的值是:{i1},参数2的值是:{i2},参数3的值是:{s}");};action3(1,"a","abc");}public void Method1() {Console.WriteLine("This Method1");}public void Method2(int a,int b) { Console.WriteLine("This Method2"); }}

八、匿名委托之Func

Func匿名委托与Action相似,但是Func委托代表有返回类型的委托。

Func至少0个输入参数,至多16个输入参数,根据返回值泛型返回。必须有返回值,不可void

Func 表示没有输入参参,返回值为int类型的委托。

Func<object,string,int> 表示传入参数为object, string ,返回值为int类型的委托。

Func<object,string,int> 表示传入参数为object, string, 返回值为int类型的委托。

Func<T1,T2,T3,int> 表示传入参数为T1,T2,T3(泛型),返回值为int类型的委托。

public void Operate() 
{// 无参数,只要返回值 Func<int> fun1 = new Func<int>(FunWithNoPara);int result1 = fun1();Console.WriteLine(result1);Console.WriteLine("----------------------------");Func<int> fun2 = delegate { return 19; };int result2 = fun2();Console.WriteLine(result2);Console.WriteLine("----------------------------");Func<int> fun3 = () => { return 3; };int result3 = fun3();Console.WriteLine(result3);Console.WriteLine("----------------------------");//有一个参数,一个返回值Func<int, int> fun4 = new Func<int, int>(FunWithPara);int result4 = fun4(4);Console.WriteLine($"这里是一个参数一个返回值的方法,返回值是:{result4}");Console.WriteLine("----------------------------");// 使用委托Func<int, string> fun5 = delegate (int i) { return i.ToString(); };string result5 = fun5(5);Console.WriteLine($"这里是一个参数一个返回值的委托,返回值是:{result5}");Console.WriteLine("----------------------------");// 使用匿名委托Func<int, string> fun6 = (int i) =>{return i.ToString();};string result6 = fun6(6);Console.WriteLine($"这里是一个参数一个返回值的匿名委托,返回值是:{result6}");Console.WriteLine("----------------------------");// 多个输入参数Func<int, string, bool> fun7 = new Func<int, string, bool>(FunWithMultiPara);bool result7 = fun7(2, "2");Console.WriteLine($"这里是有多个输入参数的方法,返回值是:{result7}");Console.WriteLine("----------------------------");// 使用委托Func<int, string, bool> fun8 = delegate (int i, string s){return i.ToString().Equals(s) ? true : false;};bool result8 = fun8(2, "abc");Console.WriteLine($"这里是有多个输入参数的委托,返回值是:{result8}");Console.WriteLine("----------------------------");// 使用匿名委托Func<int, string, bool> fun9 = (int i, string s) =>{return i.ToString().Equals(s) ? true : false;};bool result9 = fun9(45, "ert");Console.WriteLine($"这里是有多个输入参数的匿名委托,返回值是:{result9}");Console.ReadKey();}public int FunWithNoPara(){return 10;}public int FunWithPara(int i){return i;}public bool FunWithMultiPara(int i, string s){return i.ToString().Equals(s) ? true : false;}

九、委托总结

  1. 委托封装了包含特殊返回值和一组参数行为,类似于单一方法接口。
  2. 委托类型声明中描述的类型签名决定了方法哪个方法可用于委托实例,同时也决定了调用签名。
  3. 创建委托实例,需要一个方法以及(对于实例方法来说)调用方法的目标。
  4. 委托实例是不易变的。
  5. 每个委托实例都包含一个调用列表——一个操作列表。
  6. 委托实例可以合并到一起,也可以从一个委托实例中删除另一个。

十、参考资料

https://learn.microsoft.com/zh-cn/dotnet/api/system.func-1?view=net-7.0

https://learn.microsoft.com/zh-cn/dotnet/csharp/programming-guide/delegates/

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

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

相关文章

Vue2或者uniapp 中 使用 iframe 嵌入本地 HTML 页面 并 相互通信。

1.使用 iframe 嵌入本地 HTML 页面&#xff08;以pdfjs为例&#xff09; 在 public 文件夹下新建 static 文件夹&#xff0c;然后将 html 文件及相关引用拷贝到 static 文件夹下 uniapp在src下新建hybrid文件 vue 文件完整代码 <template><div class"wrap&q…

java实现简单连点器1

这段代码是使用Java的AWT库来实现模拟鼠标点击的操作。它创建了一个Robot对象&#xff0c;通过该对象可以模拟鼠标和键盘操作。在这段代码中&#xff0c;首先设置了点击位置的坐标&#xff08;x和y&#xff09;&#xff0c;点击间隔时间&#xff08;interval&#xff09;以及点…

顶级数据恢复工具—— 最全的15个数据恢复软件榜单

在这个信息为王的数字时代&#xff0c;关键数据的丢失对个人和企业来说都可能是灾难性的。无论是由于意外删除、硬件故障还是恶意攻击&#xff0c;拥有强大的数据恢复解决方案都是至关重要的。在本综合指南中&#xff0c;我们将探索市场上最好的数据恢复软件&#xff0c;包括顶…

java+python农村集体产权管理系统php+vue

注册、登陆该系统根据操作权限的不同分为管理员和用户两种&#xff0c;新用户在登陆前要进行用户注册&#xff0c;注册完成后方可进行登陆。 本次设计的关键问题处理&#xff0c;主要有如下几点&#xff1a; (1&#xff09;本次开发&#xff0c;采用主流Thinkphp框架进行开发&a…

KernelSHAP vs TreeSHAP

Kernel SHAP和Tree SHAP都用于近似Shapley值。Tree SHAP要快得多。缺点是它只能用于基于树的算法&#xff0c;如随机森林和xgboost。另一方面&#xff0c;Kernel SHAP是模型不可知的(model agnostic)&#xff0c;这意味着它可以与任何机器学习算法一起使用。我们将比较这两种近…

如何把 Oracle 19C RAC+DG加入到ORACLE EM 13C监控

平时见ORACLE 19c rac single dg的部署很多了&#xff0c;ORACLE em 13c 的安装也很多了,但如何把手工部署的oracle 19c rac dg 添加到em 13c 中去&#xff0c;让EM13C 来实现对RACDG的监控&#xff0c;主要是DG的EM13C的监控&#xff0c;还没有看到&#xff0c;大部分都是直接…

AI编译优化技术“loop tiling“、“ordering“、“caching“和“unrolling“

文章目录 概念例子 概念 在计算机科学和编程中&#xff0c;特别是在高性能计算和优化编译器设计领域&#xff0c;“loop tiling”、“ordering”、"caching"和"unrolling"是一些常见的术语&#xff0c;它们涉及到改进程序性能的不同策略。下面分别解释这些…

2023极客大挑战-AGRT战队wp

目录 RE Shiftjmp 点击就送的逆向题 幸运数字 ​编辑 砍树 小黄鸭 flower-or-tea mySelf 是男人就来扎针 听说cpp很难&#xff1f; Easymath 寻找初音未来 Rainbow 浪漫至死不渝 ezandroid Pwn nc_pwntools password ret2text write1 ret2libc ezpwn wr…

力扣23. 合并 K 个升序链表(java,最小堆解法)

Problem: 23. 合并 K 个升序链表 文章目录 题目描述思路解题方法复杂度Code 题目描述 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 思路 1.对于合并k个有序链表&#xff0c;我们较为容易想…

高翔:《自动驾驶与机器人中的SLAM技术 》-Slam_in_autonomous_driving 编译过程中遇到的问题

使用的环境是ubuntu20.04 问题1.安装g2o没有问题&#xff0c;不过在编译整个项目工程时候报错&#xff1a; ”openmp_mutex.h: 30:10: fatal error: g2o/config.h: No such file or directory“: 解决办法&#xff1a; 只需要将/thirdparty/g2o/build/g2o下的config.h放到/…

shiro整合redis

shiro整合redis 前言&#xff1a;shiro默认的session是存储在jvm内存中的&#xff0c;这样会导致java服务内存占用更大以及一旦服务器宕机或者版本迭代需要重启服务时&#xff0c;缓存中的数据不能恢复&#xff0c;导致用户需要重新登录认证&#xff0c;体验很差。因此利用第三…

C++ STL : std::list,源码面前,了无秘密,大裤衩啥颜色材质给你写的明明白白,哈哈

eat std::list source code list的好处是每次插入或删除一个元素&#xff0c;就配置或释放一个元素空间。因此&#xff0c;list对于空间的运用有绝对的精准&#xff0c;一点也不浪费。而且&#xff0c;对于任何位置的插入和元素移除都永远是常数时间。 可惜了当下有点忙能力欠…

c语言练习12周(15~16)

编写int fun(char s[])函数&#xff0c;返回字串中所有数字累加和 题干编写int fun(char s[])函数&#xff0c;返回字串中所有数字累加和。 若传入串"k2h3yy4x"返回整数9&#xff1b;若传入串"uud9a6f7*"返回整数22 //只填写要求的函数 int fun(cha…

JSON详细教程

&#x1f60a;JSON详细教程 &#x1f6a9;JSON简介☃️JSON语法规则&#x1f50a;JSON和JavaScript对象的区别 ☃️JSON数据类型字符串&#x1f50a;数字&#x1f50a;布尔值&#x1f50a;数组&#x1f50a;对象&#x1f50a;Null ☃️JSON对象&#x1f50a;访问JSON对象的值&a…

堆的应用(堆排序、Top-K问题)

文章目录 1 堆排序2 Top-K问题 1 堆排序 堆排序是一种基于二叉堆&#xff08;通常使用数组实现&#xff09;的排序算法。 它的基本思想是利用堆这种数据结构的性质&#xff0c;通过建立一个堆&#xff08;大堆或小堆&#xff09;&#xff0c;使得堆的根节点是所有节点中的最大值…

在线 SQL 模拟器SQL Fiddle使用简介

在线 SQL 模拟器SQL Fiddle使用简介 有时候&#xff0c;我们想去验证 SQL语句&#xff0c;却缺少数据库环境&#xff0c;那该怎么办呢&#xff1f; 这时候在线 SQL 模拟器就有了用武之地。SQL 模拟器免安装&#xff0c;可以在网页直接运行 SQL 。 SQL Fiddle 支持 MySQL、Orac…

C++ Qt QString用法详解与代码演示

作者:令狐掌门 技术交流QQ群:675120140 csdn博客:https://mingshiqiang.blog.csdn.net/ 文章目录 创建和初始化长度和容量修改字符串字符串比较查找和提取数值转换arg格式化`arg` 的基本用法精确控制占位符多占位符的复杂替换使用大括号占位符注意事项迭代Unicode 和编码QSt…

SystemVerilog 入门

文章目录 包定义SystemVerilog 数据类型结构体 SystemVerilog 过程块可嵌套模块接口 System Verilog 的优点 提高了硬件建模能力、编码效率和抽象能力&#xff1b;RTL 级、系统级行为描述&#xff1b; 增强了验证能力和为大规模复杂设计编写有效、无竞争测试程序的断言功能&am…

spring-framework-5.2.25.RELEASE源码环境搭建

环境准备 spring-framework-5.2.25.RELEASEIntelliJ IDEA 2022.3.1java version “11.0.20” 2023-07-18 LTSGradle 5.6.4java version “1.8.0_301” 下载spring-framework-5.2.25.RELEASE源码 git clone https://gitee.com/QQ952051088/spring.git cd spring gradlew buil…

[学习记录]Node event loop 总结流程图

文章目录 文章来源根据内容输出的流程图待处理遗留的问题参考 文章来源 详解JavaScript中的Event Loop&#xff08;事件循环&#xff09;机制 根据内容输出的流程图 待处理 这里从polling阶段开始 好像有些问题 遗留的问题 为什么“在I/O事件的回调中&#xff0c;setImmediate…