【读书笔记】C#高级编程 第八章 委托、lambda表达式和事件
(一)引用方法
委托是寻址方法的.NET版本。委托是类型安全的类,它定义了返回类型和参数的类型。委托不仅包含对方法的引用,也可以包含对多个方法的引用。
Lambda表达式与委托直接相关。当参数是委托类型时,就可以使用lambda表达式实现委托引用的方法。
(二)委托
当要把方法传递给其它方法时,需要使用委托。委托是一种特殊类型的对象,其特殊之处在于,我们以前定义的所有对象都包含数据,而委托包含的只是一个或多个方法的地址。
1、声明委托
委托使用关键字 delegate 进行定义。
例子:
定义一个返回类型为void参数为一个int的名为IntMethodInvoker的委托
- delegate void IntMethodInvoker(int x);
因为定义委托基本上就是定义一个新类,所以可以在定义类的任何相同地方定义委托。可以在委托定义上应用常见的访问修饰符:public、private、protected等。
2、使用委托
- 1 delegate int CalculateMethodInvoker(int x, int y);
- 2 class Program
- 3 {
- 4 static void Main(string[] args)
- 5 {
- 6 CalculateMethodInvoker calculateMethodInvoker = CalculateMethodHelper.Sum;
- 7 int x = 100, y = 200;
- 8 Console.WriteLine("x,y相加:{0}", Calculate(calculateMethodInvoker, x, y));
- 9 calculateMethodInvoker = CalculateMethodHelper.Multiply;
- 10 Console.WriteLine("x,y相乘:{0}", Calculate(calculateMethodInvoker, x, y));
- 11 Console.ReadKey();
- 12 }
- 13 public static int Calculate(CalculateMethodInvoker calculateMethodInvoker, int x, int y)
- 14 {
- 15 return calculateMethodInvoker(x, y);
- 16 }
- 17 }
- 18 public class CalculateMethodHelper
- 19 {
- 20 public static int Sum(int x, int y)
- 21 {
- 22 return x + y;
- 23 }
- 24 public static int Multiply(int x, int y)
- 25 {
- 26 return x * y;
- 27 }
- 28 }
运行以上代码,结果如下:
为了减少输入量,只需要委托实例,就可以只传递地址的名称。这称为委托推断。
3、Action<T>和Func<T>委托
除了为每个参数和返回类型定义一个新的委托类型外,还可以使用Action<T>和Func<T>委托。
泛型Action<T>委托表示引用一个void返回类型的方法,没有泛型参数的Action类可调用没有参数的方法。
泛型Func<T>委托表示引用一个有返回值的方法。
4、多播委托
委托也可以包含多个方法。这种委托成为多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名就必须返回void;否则,就只能得到委托调用的最后一个方法的结果。多播委托识别运算符“-”、“+”、“-=”、“+=”以从委托中增加或删除方法调用。
例子:
- 1 class Program
- 2 {
- 3 static void Main(string[] args)
- 4 {
- 5 Action<int, int> calFunc = CalculateMethodHelper.Sum;
- 6 calFunc += CalculateMethodHelper.Multiply;
- 7 int x = 100, y = 200;
- 8 Calculate(calFunc, x, y);
- 9 Console.ReadKey();
- 10 }
- 11 public static void Calculate(Action<int, int> calculateMethodInvoker, int x, int y)
- 12 {
- 13 Console.WriteLine("运行结果:");
- 14 calculateMethodInvoker(x, y);
- 15 }
- 16 }
- 17 public class CalculateMethodHelper
- 18 {
- 19 public static void Sum(int x, int y)
- 20 {
- 21 Console.WriteLine("x,y相加:{0}", x + y);
- 22 }
- 23 public static void Multiply(int x, int y)
- 24 {
- 25 Console.WriteLine("x,y相乘:{0}", x * y);
- 26 }
- 27 }
如果通过委托调用的其中一个方法抛出异常,整个迭代就会停止。解决的方法是,使用Delegate类中定义的GetInvocationList()方法获取Delegate对象数组,再使用循环遍历执行,在过程中捕获异常,来继续下一次迭代。
5、匿名方法
匿名方法是用作委托的参数的一段代码。
例子:
- Action<int, int> calFunc = delegate (int i, int j)
- {
- Console.WriteLine("x,y相加:{0}", i + j);
- };
在匿名方法中不可使用跳转语句(break、goto或continue),在匿名方法内部不能访问不安全代码,不能访问在匿名方法外部使用的ref和out参数。
(三)lambda表达式
自C#3.0开始,可以使用新的语法把实现代码赋予委托,只要有委托参数类型的地方,就可以使用lambda表达式。
例子:
- Action<int, int> calFunc = (i, j) =>
- {
- Console.WriteLine("x,y相加:{0}", i + j);
- };
1、参数
lambda表达式有几种定义参数的方式。如果只有一个参数,只写出参数名就足够了。如果除一个参数以外,需要圆括号把参数名括起来。
例子:
- Action<int> one = i =>
- {
- //方法内容
- };
- Action<int, int> two = (i, j) =>
- {
- //方法内容
- };
2、多行代码
如果lambda表示只有一条语句,在方法块内就不需要花括号和return语句,因为编译器会隐式添加return。
例子:
- Func<int> lambdaOne = () => 0;
如果实现代码超过一行,就需要使用return语句显式返回。
例子:
- Func<int> lambdaOne = () =>
- {
- int i = 0;
- i++;
- ++i;
- return i;
- };
3、闭包
通过lambda表达式可以访问lambda表达式块外部的变量。这称为闭包。
例子:
- int param = 10;
- Action<int> lambdaSecond = (i) =>
- {
- Console.WriteLine(i + param);
- };
- lambdaSecond(3);
- Console.ReadKey();
运行以上代码,结果如下:
(四)事件
事件基于委托,为委托提供了一种发布/订阅机制。
例子:
- 1 class Program
- 2 {
- 3 static void Main(string[] args)
- 4 {
- 5 AlarmClock alarmClock = new AlarmClock();
- 6 Student zsStudent = new Student("张三");
- 7 alarmClock.ItsGetUpClockEvent += zsStudent.ItsGetUpClock;
- 8 alarmClock.ItsGetUpClock();
- 9 Student lsStudent = new Student("李四");
- 10 WeakEventManager<AlarmClock, EventArgs>.AddHandler(alarmClock, "ItsGetUpClockEvent", lsStudent.ItsGetUpClock);//弱事件
- 11 alarmClock.ItsGetUpClock();
- 12 Console.ReadKey();
- 13 }
- 14
- 15 }
- 16 //事件发布类
- 17 public class AlarmClock
- 18 {
- 19 public event EventHandler<EventArgs> ItsGetUpClockEvent;
- 20 public void ItsGetUpClock()
- 21 {
- 22 Console.WriteLine("时间到,起床了!");
- 23 ItsGetUpClockEvent?.Invoke(this, new EventArgs());
- 24 }
- 25 }
- 26 //事件侦听类
- 27 public class Student
- 28 {
- 29 public string Name { get; set; }
- 30 public Student(string name)
- 31 {
- 32 this.Name = name;
- 33 }
- 34 public void ItsGetUpClock(object sender, EventArgs e)
- 35 {
- 36 Console.WriteLine("{0}关掉闹钟,起床了。",Name);
- 37 }
- 38 }
【读书笔记】C#高级编程 第八章 委托、lambda表达式和事件的更多相关文章
- C#编程 委托 Lambda表达式和事件
委托 如果我们要把方法当做参数来传递的话,就要用到委托.简单来说委托是一个类型,这个类型可以赋值一个方法的引用. 声明委托 在C#中使用一个类分两个阶段,首选定义这个类,告诉编译器这个类由什么字段和方 ...
- 读书笔记 - js高级程序设计 - 第八章 BOM
BOM的核心对象是window 它表示浏览器的一个实例,在浏览器中,window对象有双重角色,它既是通过js访问浏览器窗口的一个接口,又是ECMAScript规定的Global对象,这意味着在网 ...
- 读书笔记 - js高级程序设计 - 第七章 函数表达式
闭包 有权访问另一个函数作用域中的变量的函数 匿名函数 函数没有名字 少用闭包 由于闭包会携带包含它的函数的作用域,因此会比其它函数占用更多的内存.过度使用闭包可能会导致内存占用过多,我们建议读者 ...
- C#学习笔记三(委托·lambda表达式和事件,字符串和正则表达式,集合,特殊的集合)
委托和事件的区别 序号 区别 委托 事件 1 是否可以使用=来赋值 是 否 2 是否可以在类外部进行调用 是 否 3 是否是一个类型 是 否,事件修饰的是一个对象 public delegate vo ...
- C#高级编程(第9版) 第08章 委托、lambda表达式和事件 笔记
本章代码分为以下几个主要的示例文件: 1. 简单委托 2. 冒泡排序 3. lambda表达式 4. 事件示例 5. 弱事件 引用方法 委托是寻址方法的.NET版本.在C++中函数 ...
- Hadoop学习笔记(7) ——高级编程
Hadoop学习笔记(7) ——高级编程 从前面的学习中,我们了解到了MapReduce整个过程需要经过以下几个步骤: 1.输入(input):将输入数据分成一个个split,并将split进一步拆成 ...
- Java并发编程的艺术读书笔记(2)-并发编程模型
title: Java并发编程的艺术读书笔记(2)-并发编程模型 date: 2017-05-05 23:37:20 tags: ['多线程','并发'] categories: 读书笔记 --- 1 ...
- Java并发编程的艺术读书笔记(1)-并发编程的挑战
title: Java并发编程的艺术读书笔记(1)-并发编程的挑战 date: 2017-05-03 23:28:45 tags: ['多线程','并发'] categories: 读书笔记 --- ...
- 《Essential C++》读书笔记 之 C++编程基础
<Essential C++>读书笔记 之 C++编程基础 2014-07-03 1.1 如何撰写C++程序 头文件 命名空间 1.2 对象的定义与初始化 1.3 撰写表达式 运算符的优先 ...
随机推荐
- 我不就是吃点肉,应该没事吧——爬取一座城市里的烤肉店数据(附完整Python爬虫代码)
写在前面的一点屁话: 对于肉食主义者,吃肉简直幸福感爆棚!特别是烤肉,看着一块块肉慢慢变熟,听着烤盘上"滋滋"的声响,这种期待感是任何其他食物都无法带来的.如果说甜点是" ...
- Mysql错误:The server time zone value is unrecognized or represents more than one time zone
方法1.修改Mysql的时区为东8区,执行如下命令即可: PS:这种方式每次开机都要配置的 set global time_zone='+8:00' 方法2.配置改成这样的 spring.dataso ...
- List集合_介绍&常用方法和ArrayList集合
List集合 我们掌握了Collection接口的使用后,再来看看Collection接口中的子类,他们都具备那些特性呢? 接下来,我们一起学习Collection中的常用几个子类(java.util ...
- 挑战30天写操作系统-day1-从计算机结构到汇编程序入门
先动手操作 软盘映像文件制作:先采用二进制编辑器编辑我们所需要的映像文件helloos.img 二进制编辑器下载链接:Bz - c.mos (vcraft.jp) 制作好之后,可以选择写入软盘,通过软 ...
- RocketMQ之消费者启动与消费流程
vivo 互联网服务器团队 - Li Kui 一.简介 1.1 RocketMQ 简介 RocketMQ是由阿里巴巴开源的分布式消息中间件,支持顺序消息.定时消息.自定义过滤器.负载均衡.pull/p ...
- 利用噪声构建美妙的 CSS 图形
在平时,我非常喜欢利用 CSS 去构建一些有意思的图形. 我们首先来看一个简单的例子.首先,假设我们实现一个 10x10 的格子: 此时,我们可以利用一些随机效果,优化这个图案.譬如,我们给它随机添加 ...
- (一)java基础篇-----认识java
1.简单介绍java起源: 1995年,詹姆斯-高斯林在sun公司开发出java编程语言.到2010年,sun公司被Oracle公司收购,而詹姆斯-高斯林也离开了Oracle公司.所以,如今想要安转j ...
- MyBatis-Plus联表查询的短板,终于有一款工具补齐了
原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 哈喽大家好啊,我是Hydra. mybatis-plus作为mybatis的增强工具,它的出现极大的简化了开发中的数据库操作,但是长久以来,它的 ...
- SpringBoot使用CORS的addCorsMappings中会遇到的问题
跨域需要后端需要设置响应的跨域头 如下 public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/ ...
- 利用DockerHub在Centos7.7环境下部署Nginx反向代理Gunicorn+Flask独立架构
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_165 上一篇文章:Docker在手,天下我有,在Win10系统下利用Docker部署Gunicorn+Flask打造独立镜像,是在 ...