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表达式实例化委托

语法:参数列 =>语句或语句块

用法规则:

  1. “Lambda表达式”的参数数量必须和“委托”的参数数量相同;
  2. 如果“委托”的参数中包括有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#委托的详细总结的更多相关文章

  1. C#委托的详细使用

    代码如下: public delegate void GreetingDelegate(string name);//定义委托,它定义了可以代表方法的类型 class Program { public ...

  2. C# 从CIL代码了解委托,匿名方法,Lambda 表达式和闭包本质

    前言 C# 3.0 引入了 Lambda 表达式,程序员们很快就开始习惯并爱上这种简洁并极具表达力的函数式编程特性. 本着知其然,还要知其所以然的学习态度,笔者不禁想到了几个问题. (1)匿名函数(匿 ...

  3. 理解js事件冒泡事件委托事件捕获

    js事件冒泡 javascript的事件传播过程中,当事件在一个元素上出发之后,事件会逐级传播给先辈元素,直到document为止,有的浏览器可能到window为止,这就是事件冒泡现象. <di ...

  4. UE4技术总结——委托

    UE4技术总结--委托 目录 UE4技术总结--委托 一.定义 二.用法 2.1 声明与调用委托 2.1.1 单播委托 2.1.1.a 声明 2.1.1.b 绑定 2.1.1.c 执行委托 2.1.1 ...

  5. C#由变量捕获引起对闭包的思考

    前言 偶尔翻翻书籍看看原理性的东西确实有点枯燥,之前有看到园中有位园友说到3-6年工作经验的人应该了解的.NET知识,其中就有一点是关于C#中的闭包,其实早之前在看书时(之前根本不知道C#中还有闭包这 ...

  6. [知识库分享系列] 二、.NET(ASP.NET)

    最近时间又有了新的想法,当我用新的眼光在整理一些很老的知识库时,发现很多东西都已经过时,或者是很基础很零碎的知识点.如果分享出去大家不看倒好,更担心的是会误人子弟,但为了保证此系列的完整,还是选择分享 ...

  7. C#由变量捕获引起对闭包

    C#由变量捕获引起对闭包的思考   前言 偶尔翻翻书籍看看原理性的东西确实有点枯燥,之前有看到园中有位园友说到3-6年工作经验的人应该了解的.NET知识,其中就有一点是关于C#中的闭包,其实早之前在看 ...

  8. CLR类型设计之泛型(二)

    在上一篇文章中,介绍了什么是泛型,以及泛型和非泛型的区别,这篇文章主要讲一些泛型的高级用法,泛型方法,泛型接口和泛型委托,协变和逆变泛型类型参数和约束性,泛型的高级用法在平时的业务中用的不多,多用于封 ...

  9. C# 与 Java 的一些差异

    如果你是 Java 开发人员,则可以在 Xamarin 平台上充分利用你的技能和现有代码,同时获得 C# 的代码重用优势.你会发现 C# 语法与 Java 语法非常相似,这两种语言提供非常类似的功能. ...

随机推荐

  1. php+nginx 整合

    php编译 https://www.cnblogs.com/php-linux/p/12360858.html nginx编译 https://www.cnblogs.com/php-linux/p/ ...

  2. HTML <del> 标签

    HTML <del> 标签 什么是<del> 标签? 定义文档中已被删除的文本. 实例 a month  is <del>25</del> 30 day ...

  3. 蒲公英 &#183; JELLY技术周刊 Vol.26: 请问您这个月要来点肝么?

    蒲公英 · JELLY技术周刊 Vol.26 今年的十月,不知道大家在 TODO List 上新增了多少条目准备尝鲜,你可能已经准备了 Vue3.Webpack5 以及 React v17.0 RC, ...

  4. 从0实现python批量爬取p站插画

    一.本文编写缘由 很久没有写过爬虫,已经忘得差不多了.以爬取p站图片为着手点,进行爬虫复习与实践. 欢迎学习Python的小伙伴可以加我扣群86七06七945,大家一起学习讨论 二.获取网页源码 爬取 ...

  5. 应用LORAWAN技术的好处是什么

    LoRaWAN现在一种非常流行的LPWA通信标准,在ISM(工业.科学.医疗)频段使用未经许可的无线电频谱,频率约为900MHz到430MHz(世界各地的标准各不相同). 物联网连接环境除了智能家庭联 ...

  6. PHP实现页面静态化的简单方法分享

    为什么要页面静态化? 1.动态文件执行过程:语法分析-编译-运行 2.静态文件,不需要编译,减少了服务器脚本运行的时间,降低了服务器的响应时间,直接运行,响应速度快:如果页面中一些内容不经常改动,动态 ...

  7. Deployment YAML方式创建Nginx服务

    replication controller Replication Controller为Kubernetes的一个核心内容,应用托管到Kubernetes之后,需要保证应用能够持续的运行,Repl ...

  8. 敲黑板:InnoDB的Double Write,你必须知道

    世界上最快的捷径,就是脚踏实地,本文已收录[架构技术专栏]关注这个喜欢分享的地方. 前序 InnoDB引擎有几个重点特性,为其带来了更好的性能和可靠性: 插入缓冲(Insert Buffer) 两次写 ...

  9. [Luogu P1268] 树的重量 (巧妙的构造题)

    题面 传送门:https://www.luogu.org/problemnew/show/P1268 Solution 这是一道极其巧妙的构造题 先做一个约定[i,j]表示从i到j的距离 我们可以先从 ...

  10. Mybatis执行SQL的完整过程及四大组件介绍

    一切的执行从MapperProxy开始,MapperProxy是MapperProxyFactory使用SqlSession创建出来的.所以MapperProxy中包含SqlSession. 可以看到 ...