《C#本质论》读书笔记分享<二>委托,事件,lambda
重读Csharp本质论一书,发现上面已经记录1500多条注释笔记,整理一下分享出来,里面会有对笔记的复制整理,也有一些新的思考。
PS:该书真是神书,除了基础语法以外,还讲解了“为什么”“如何做”这种问题,让读者知其然,也知其所以然。每个章节的内容深入浅出,覆盖面较广,有时还会提醒开发者,应该养成什么样的编码风格,无论是初学者还是有一定Csharp基础的开发者,都能有所收获。
关于委托
委托概述
委托的诞生是为了解决一个痛点:很多时候,我们传入某个类型完整的实例引用,却只是为了调用其中的一个方法,所以急需要一种,可以单独传入方法的语法。
于是委托应运而生,委托的核心就是支持变量对方法的引用,有了这个引用,方法就有了可变性而且可以作为参数传递。
委托声明
以delegate关键字加上方法签名的方式进行声明
public delegate bool FuncName(int first,int second)
委托延伸
-
委托也是类型,是一种特殊类,继承自System.delegate但是其实现在都是继承自System.MuyticastDelegate,内部包含两个关键信息MethodInfo(方法签名信息)还有Target(实际引用的对象),当为static委托时,Target应该为Null.
-
委托一旦被初始化引用后不可再更改
-
委托写作参数时,有个转换性,即符合方法签名条件的都可以转换为目标委托参数,但是多个委托类型之间是不存在转换性额度,即哪怕方法结构签名等完全一致,也无法相互转换.
-
委托有一些预设的元组比如Action,Func完全可以当作普通的委托使用
关于多播委托
普通委托使用+=符号串联起来的委托链,就是多播委托,一般用于实现订阅发布模式.
但是有一些严重的问题:
- NULL值问题: 订阅者尚未注册任何接收方法,则可能出现空引用异常
解决方法:使用委托前判空,或者使用 ?( null校验符,null校验符有个特殊逻辑是 通过NULL校验后该值就不允许再被其他线程置为NUll) - 异常中断问题:引用链中如果有一个委托引发了异常,后续的委托都将收不到多播消息
- 使用旧的委托链问题:每次使用+=(-=)符号后,会生成一个新的引用指向新的委托链,旧引用指向的委托链不变, 这就存在其他线程使用旧引用链的可能
- 误用符号问题:误用=号会出现,前面的链全部被注销,生成一个新的链
- 外部调用问题:已经声明好的委托,允许在包容类外部被手动调用,这是一个不合理的情况. TIp 这个书上写的不详细,理解不清楚
关于事件
事件的使用步骤:
参考https://www.cnblogs.com/chunhui212/p/5892489.html
事件的存在意义:
事件可以理解为对多播委托的再封装,其实事件的诞生就是为了解决多播委托的上述的五个问题。
完整的样例
一个完整的标准的事件声明:
public class MyEventArgs :System.EventArgs{
int x{set,get}
public MyEventArgs (int x){
this.x = x;
}
}
public delegate void MyEventHandler(object sender, MyEventArgs args);
public event MyEventHandler myEvent = delegate{};
一个完整的标准的事件注册:
public void TestMethod(object sender, MyEventArgs args)
{
....
}
myEvent += TestMethod;
一个完整的标准的事件**:
包容类.myEvent (this,new MyEventArgs (999));
// 或者 包容类.myEvent?.Invoke (this,new MyEventArgs (999));
上述样例的补充说明:
- 一个完整的事件委托(MyEventHandler ) 必须要包含两个参数,
- 一个是object类型的sender,指向事件的**者,一般调用时填this,而静态事件则会填null,
- MyEventArgs 继承自System.EventArgs, 其内部包含事件传播时需要的数据,
也就是说事件传递数据时,哪怕仅仅只是个Int,也要包含在EventArgs里面.这是一种通用规范.
其实EventArgs主要作用是包含了一个Empty属性,可以用来表明没有参数数据.
EventHandler
额外提一下EventHandler,EventHandler是CLR预定义的事件委托,其中的T就是上述的EventArgs的派生类,T不指定时,默认为EventArgs, 而sender默认为object(无需泛型)
事件使用规范

其他补充阅读;
https://www.cnblogs.com/chunhui212/p/5887579.html
关于Lambda表达式
Lambda概述
Lambda表达式分为
- 语句Lambda(其实就是可能包含多个语句表达式),
- 表达式Lambda(其实就是只包含一个完整return表达式的Lambda)
写法有
(int x,int y)=>{return x>y} 正常写法( x,y)=>{return x>y} 省略形参类型x=>{return x+1} 省略括号和形参类型()=>{.....} 无参数
总结三个Lambda的原则
- 省略原则:原则上CLR可以推断的类型(参数类型)和符号(括号,大括号,return关键字)都可以省略
- 类型无关原则:Lambda不跟任何类型相关,那怕是Object(比如Lambda.Tostring()是错误的),不要尝试让Lambda跟任何类型交互(比如转换)
- 封闭原则:Lambda外部的代码无法跳到内部(比如goto),内部也无法跳转外部(比如case中的break),内部无法校验外部的值是否已经初始化(如果没有初始化会引起编译警告).被lambda捕获的局部变量会延长其生命周期
智能推荐
C#读书笔记
此书为《C#入门经典(C#6.0&Visual Studio 2015)(第七版)》,购于2016年底 购买此书是因为工作需要接触部分C#代码,而那时我对面向对象编程的概念认识尚浅,工作接触的代码又比较庞大,于是寄希望于此书,希望能快速上手C#,了解基本的知识,避免闹笑话。 刚拿到这本书时,我急于求成,加上书前半部分的内容也很入门(读书时跳过了),约2、3周便利用闲暇时间读完了,这份读书笔...
【C#本质论 十】合式类型(一)重写Object成员及操作符重载
第一次看到这章的标题有点懵,啥是合式类型,是一种值类型和引用类型之外的类型么,以前也没有听说过呀?其实并不是,合式类型其实说白了就是合适的类型,如何定义类型,如何操作类型才更好,如何创建合适的值类型和引用类型? 这一章的内容比较杂,基本上类似于基础部分的终结之章,回顾下之前学习的章节,1-5章介绍了结构性编程的基础知识,6-10章来介绍面向对象的内容,加上接下来11章对异常处理的延伸学习后,基本内...
C#图解教程读书笔记
注:会C语言学C#语法会容易很多,很多都是想通的,这本书讲的挺通俗易懂的,适合初学者 2.7.3 格式化字符串 2.7.5 格式化数字字符串 3.6 定义类型 3.7 栈和堆 程序运行中,他的数据必须存储在内存中。运行中的程序使用两个内存区域来存储数据:栈和堆 栈:后进先出 堆:可以以任意顺序存入和移除 3.8 值类型和引用类型 值类型直接存储其值,而引用类型存储对其值的引用。 4.3...
【读书笔记】编写高质量代码改善C# 建议32-38(⭐泛型和委托)
32、总是优先考虑泛型 例如实现自己的List类 33、避免在泛型类型中声明静态成员 如果不想要不同类型共享相同是属性,就别定义静态成员 34、为泛型参数设定约束 为泛型添加约束后,可以使用约束相应的功能 例如new() 或者 :Person(某个自定义的类) 35、使用default为泛型变量指定初始值 36、使用FCL中的委托声...
C# 实现委托(delegate)事件(二)
在某个功能实现时要调用某个窗体的某个事件来激发当前功能的某个按钮,举例说明: 在利用ArcEngine进行二次开发时,当图层树上的某一图层关闭后,对应的打开的属性表也要进行关闭,此时就需要用到委托和事件。 具体实现如下: 1. 定义全局的委托事件 2. 在属性表窗体中调用该事件,调用方法如下所示: 3. 在图层右侧事件中调用该事件的窗体关闭方法: 4.此时,右侧图层移除后,打开的属性表的窗口也会随...
猜你喜欢
C#学习笔记:事件与委托
参考书目:C#6.0学习笔记——从第一行C#代码到第一个项目设计(作者周家安) 学习目的:掌握事件与委托的用法,定义一个委托类型,作为响应按下空格键这一事件。 运行结果如下: ...
C# 委托(二)—— 多播委托与事件
目录 1 多播委托 1.1 多播委托的实例化 1.2 多播委托的调用与返回结果 1.3 多播委托的逐个调用 2 事件 2.1 事件的本质 2.2 事件用法三步曲 2.3 事件与多播委托的区别 上一篇文章中,介绍了委托的基本用法(传送门:https://blog.csdn.net/wnvalentin/article/details/81840339)。本文中,我们来了解一下常用的事件机制,以及事件...
c#事件委托
代码是理解的亲娘 直接开干 懂了么? 不管,继续 哇哈哈! 没事 来吧! Pub.issueComputer(); //触发事件 Pub.issureLife(); Console.WriteLine(); Console.WriteLine("一年以后"); Pub.OnPubComputer -= new Pu...
冒泡排序,及改进方式,性能优化400%>>>附图解加源码
首先源码附上,源码中带有注释,看不懂没关系,源码后面附带图解,最后附上代码效率提升图 源码如下: 方案一:其实实现很简单,两层循环,每次内层迭代出最大的一个值,将其放入数组最后一个位置,外层循环的末端便往前移一位。其原理如下图 方案一代码块: 方案二:优化改进 仔细观察上面的图,我们不难发现当迭代到图下这样的情况时,其实已经全排序好了,但是我们还是需要对它进行1,2,3,4,5,6的迭代,这些情况...
css3常用选择器
先介绍一下基本选择器,如下几种 *:通配符。选择页面的所有元素 E:元素选择器。对页面的一些元素进行选择,如p,div,li等 .class:类选择器 #id:id选择器。一个Id在一个页面中只能选择,这是和类选择器的区别 E F:后代选择器。如ul li。选中ul下的li E>F:子元素选择器。如下,可以用 h1 > strong {color:red;}使h1的子元素strong变...
