C#委托的详细总结
1.什么是委托
委托是C#中一种类型,它的作用相当于C语言中的函数指针,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用if-else(Switch)语句,同时使得程序具有更好的可扩展性。
委托和类是同级别的,我们可以直接将delegate看成为关键字class,区别为class里存放的是一系列方法,属性,字段,事件,索引。而delegate里存放的是一系列具有相同类型参数和返回回类型的方法的地址的地址。可以看着为储存方法的载体。
2.声明委托
delegate <函数返回类型> 委托名(函数参数)
例:public delegate void MyDelegate(string name);
3.实例化委托
(1) 常规实例化委托
语法:<委托名> 实例化名 = new <委托名>(注册函数)
注意:注册函数不包含参数,或者可以直接将一个注册函数赋值给委托。 例:
MyDelegate _md = new MyDelegate(method);
(2)匿名方法实例化委托
语法: <委托类型> <实例化名>=delegate(<函数参数>){函数体}; 例:
MyDelegate md = delegate(string s)
{
Console.WriteLine(s);
};
(3)使用Lambda表达式实例化委托
语法:参数列 =>语句或语句块
用法规则:
- “Lambda表达式”的参数数量必须和“委托”的参数数量相同;
- 如果“委托”的参数中包括有ref或out修饰符,则“Lambda表达式”的参数列中也必须包括有修饰符; 例:
class Test
{
public delegate void MyDelegate(out int x);//声明委托
static void Print(MyDelegate test)
{
int i;
test(out i);
Console.Write(i);
}
static void Main()
{
Print((out int x) => x = 3);
Console.Read();
}
}
这三种方法都可以实现功能,lamda表达式只是简化了委托的声明,以及委托的实例化和调用。 从下面的例子中让我们看看三者的区别:
class Program
{
//声明委托
delegate int MyDelegate(int x, int y);
static void Main(string[] args)
{
//实例化委托
//1、使用new关键字
MyDelegate _md = new MyDelegate(Sum);
//2、使用匿名方法
MyDelegate md= delegate(int x, int y)
{
return x + y;
};
//3、使用Lambda表达式
MyDelegate mdLambda = (int x, int y) => { return x + y; };
}
static int Sum(int x, int y)
{
return x + y;
}
}
4.多播委托
多播委托继承自 Delegate,即 “多路广播委托”(MulticastDelegate)。从名字就可以看出,此种委托可以像广播一样将影响信息“传播”到四面八方。多播委托类拥有一个方法调用列表,调用委托时,它就会逐一调用该列表中的方法,从而实现多重影响。
在现实生活中,多播委托的例子是随处可见的,例如某点餐的应用程序,既可以预定普通的餐饮也可以预定蛋糕、鲜花、水果等商品。在这里委托相当于点餐平台,每一个类型的商品可以理解为在委托上注册的一个方法。
4.1 多播委托的实例化
多播委托的初始化可以像普通委托一样,传入一个签名相同的实例方法。同时,多播委托重载了 += 运算符和 -= 运算符,用来向其调用列表中添加或者删除方法。调用多播委托时,方法将按照添加的顺序被依次调用。
我们定义一个简单的执行加减运算的委托,并利用+=运算符和Lambda表达式为该多播委托添加两个方法:
public delegate int AddDelegate(int a);
AddDelegate md = new AddDelegate(i => i + 10);
md += i => i - 10;
4.2 多播委托的调用与返回结果
!!!使用委托,直接md( )就相当于使用了md. Invoke()
调用上面的AddDelegate,传入一个参数10:
Console.WriteLine(md(10));
运行代码,得到结果:
0
你们有疑问吗?为什么有两个方法,怎么只有一个返回值呢?
实际上,两个方法都被调用了。案例讲解:
多播委托按照顺序调用其列表中的方法。首先,参数先调用了 i => i + 10 函数,得到了函数返回值20。然而,委托的调用并没有停止, 而是继续调用剩余的方法。然后继续对参数调用 i => i - 10 函数,得到新的返回值0,上个函数的返回值被覆盖。至此委托调用结束,返回最后调用方法的返回结果。
因此,一个有非空返回值的多播委托通常是没有意义的,因为只能获得最后一个方法的返回结果。所以通常,多播委托的返回类型为 void。
4.3 多播委托的逐个调用
那么对于返回类型不为空的多播委托来说,有没有办法得到所有方法的返回结果呢?答案是有,多播委托提供了一个 GetInvocationList () 方法,通过它可按顺序获取并执行调用列表中的方法。用法举例:
Console.WriteLine("每个都调用:");
foreach (AddDelegate f in md.GetInvocationList())
Console.WriteLine(f.Invoke(10));
如此便可逐个得到方法的输出结果:
每个都调用:
20
0
5. 泛型委托
5.1 泛型委托原型
委托也支持泛型的使用 ,泛型委托原型:delegate <委托名><T1,T2,T3...> (T1 t1,T2 t2,T3 t3...)
5.2 内置泛型委托
Func委托
Func委托代表着拥有返回值的泛型委托。Func有一系列的重载,形式如 Func<T1,T2, ... TResult>,其中TResult代表委托的返回值类型,其余均是参数类型。只有一个T时,即Func,代表该委托是无参数的。.NET封装了最多16个输入参数的Funct<>委托。
!!!若方法返回 void ,由于 void 不是数据类型,因此不能定义Func委托。
Action委托
Action委托代表返回值为空 void 的委托,它也有一些列重载,最多拥有16个输入参数。用法与Func相同。
Predicate委托
这个一般用的较少,它封装返回值为bool类型的委托,可被Func代替。
6.委托的用处
说白了,委托就是第三方,调用者告诉第三方要做什么,然后调用者就不用管了 这个委托(第三方)就会去调用方法去帮你实现。
使用委托的好处:
1.相当于用方法作为另一方法参数(类似于C的函数指针)
2.在两个不能直接调用的方法中作为桥梁,如:在多线程中的跨线程的方法调用就得用委托。
3.当不知道方法具体实现什么时使用委托,如:事件中使用委托。
C#委托的详细总结的更多相关文章
- C#委托的详细使用
代码如下: public delegate void GreetingDelegate(string name);//定义委托,它定义了可以代表方法的类型 class Program { public ...
- C# 从CIL代码了解委托,匿名方法,Lambda 表达式和闭包本质
前言 C# 3.0 引入了 Lambda 表达式,程序员们很快就开始习惯并爱上这种简洁并极具表达力的函数式编程特性. 本着知其然,还要知其所以然的学习态度,笔者不禁想到了几个问题. (1)匿名函数(匿 ...
- 理解js事件冒泡事件委托事件捕获
js事件冒泡 javascript的事件传播过程中,当事件在一个元素上出发之后,事件会逐级传播给先辈元素,直到document为止,有的浏览器可能到window为止,这就是事件冒泡现象. <di ...
- UE4技术总结——委托
UE4技术总结--委托 目录 UE4技术总结--委托 一.定义 二.用法 2.1 声明与调用委托 2.1.1 单播委托 2.1.1.a 声明 2.1.1.b 绑定 2.1.1.c 执行委托 2.1.1 ...
- C#由变量捕获引起对闭包的思考
前言 偶尔翻翻书籍看看原理性的东西确实有点枯燥,之前有看到园中有位园友说到3-6年工作经验的人应该了解的.NET知识,其中就有一点是关于C#中的闭包,其实早之前在看书时(之前根本不知道C#中还有闭包这 ...
- [知识库分享系列] 二、.NET(ASP.NET)
最近时间又有了新的想法,当我用新的眼光在整理一些很老的知识库时,发现很多东西都已经过时,或者是很基础很零碎的知识点.如果分享出去大家不看倒好,更担心的是会误人子弟,但为了保证此系列的完整,还是选择分享 ...
- C#由变量捕获引起对闭包
C#由变量捕获引起对闭包的思考 前言 偶尔翻翻书籍看看原理性的东西确实有点枯燥,之前有看到园中有位园友说到3-6年工作经验的人应该了解的.NET知识,其中就有一点是关于C#中的闭包,其实早之前在看 ...
- CLR类型设计之泛型(二)
在上一篇文章中,介绍了什么是泛型,以及泛型和非泛型的区别,这篇文章主要讲一些泛型的高级用法,泛型方法,泛型接口和泛型委托,协变和逆变泛型类型参数和约束性,泛型的高级用法在平时的业务中用的不多,多用于封 ...
- C# 与 Java 的一些差异
如果你是 Java 开发人员,则可以在 Xamarin 平台上充分利用你的技能和现有代码,同时获得 C# 的代码重用优势.你会发现 C# 语法与 Java 语法非常相似,这两种语言提供非常类似的功能. ...
随机推荐
- vm虚拟机设置共享文件夹不显示
1. 确认VMtools已经装好,开启共享文件夹,设置好共享目录 2.执行命令 sudo mount -t vmhgfs .host:/ /mnt/hgfs如果出现错误: Error: cannot ...
- go xpath
package main import ( "fmt" "github.com/antchfx/htmlquery" "net/http" ...
- kinaba 安装踩坑: FATAL Error: [elasticsearch.url]: definition for this key is missing 转
安装 https://www.jianshu.com/p/875457cb8da6 操作系统:Linux kibana 版本: 7.4.0 1. 在/etc/yum.repos.d/ 下新建 ...
- 第二十二章 Nginx性能优化
一.性能优化概述 1.我们需要了解 1.首先需要了解我们当前系统的结构和瓶颈,了解当前使用的是什么,运行的是什么业务,都有哪些服务,了解每个服务最大能支撑多少并发.比如nginx作为静态资源服务并发是 ...
- Python之包的相关
包的产生: 由于模块不断更新,越写越大,仅用单个py文件会使模块逻辑不够清晰,所以需要将模块的不同功能放入不同的py文件,然后将所有py文件放在一个目录内,这个目录就是包 包就是一个包含用__init ...
- 千万不要往 Shell 里粘贴命令!
对于用惯了 IDE 的程序员来说,在终端里敲命令可能没那么顺手,也记不住那么多复杂的命令.比较偷懒的做法就是网上搜相关的命令,复制到剪贴板往命令行窗口里一贴,完事! 但是这么做有很大的风险,为什么呢? ...
- 010_Java历史及特性
目录 Java历史 C语言 1972年 C++ 1982年 Java 1995年 Applet 图形界面的程序 J2SE Java 2 标准版 桌面 J2ME Java 2 移动版 手机 J2EE J ...
- JDK源码阅读-------自学笔记(二十五)(java.util.Vector 自定义讲解)
Vector 向量 Vector简述 1).Vector底层是用数组实现的List 2).虽然线程安全,但是效率低,所以并不是安全就是好的 3).底层大量方法添加synchronized同步标记,sy ...
- 一套轻量级销售团队管理系统【CRM】
项目描述 Hi,大家好,又到了源码分享时间啦,今天我们分享的源码一个<轻量级销售团队管理系统>,这套系统是一套轻量级的CRM系统,基于SSM的SpringBoot架构.这套项目用到很多潮流 ...
- STM32入门系列-学习STM32要掌握的内容
STM32芯片架构 STM32F103系列芯片的系统架构如下: STM32芯片基于ARM公司的Cortex-M3内核,由ST公司设计生产,内核与总线矩阵之间有I(指令).S(系统).D(数据)三条信号 ...