ASP.NET Core学习(1)

0 前言

  • .NET技术栈里兜兜转转一年多,感觉自己知道的点越来越多,系统化思考的能力却丝毫没有进境。一方面是因为自己的本职工作并非纯粹的软件开发,需要实践应用时更多依靠网上大神的分享外加粘贴复制。另一方面我也没有经过科班训练,属于只学”术“的野路子,对于软件开发的”道“知之甚少。虑及自己的职业规划,决心要修炼自己的内功。按理来说,杨中科老师的这本书并不属于"道"的范畴,但自己路子太野,就让这本书作为自己纠偏的开胃菜吧!

  • 写笔记的目的,就是为了自己能有更深入的直观理解,而直观理解的获取虽然和源码有关,但提取到之后与源码的关联性就会大大降低,所以在该系列的笔记中,代码内容并不是重点。

  • 缺陷:直观理解的优势在于理解的内容能够与自己的认知相贴合,而缺陷也正是因为过于贴合的特性,导致会因为自己认知的局限而与真实情况出现非常大的偏差。不过不害怕这种偏差,等到迷雾散开的时候,这种落差可以让我们看得更清晰。

  • 学习资料:《ASP.NET Core 技术内幕与项目实战》- 杨中科

1 对于技术的思考

  • 明白一个技术的具体使用比较简单,但用好一个技术需要有更深的理解。这些理解大致包括:
  1. 这个技术是什么?

  2. 为什么会有这个技术?

  3. 这个技术适用于什么场景?

  4. 这个技术的优缺点?

  5. 这个技术的常见用法与注意事项?

  6. 底层原理是什么?

2 C#新特性学习

  • 顶级语句:作为一种简写存在,不再限制需要在类和Main()方法中书写起始执行的语句,和python的脚本语言模式看似相同,但反编译时会发现有这种省略实际是因为框架帮助我们扩充了其它部分。

  • 全局using:利用global修饰,节省写引用的时间和空间。

  • using语句的简写:和pythonwith语句类似,用于C#非托管资源的释放,实现原理是在离开作用域后自动执行对象实例Dispose()方法。其简写,就是不再需要使用花括号套花括号的复杂形态,而可以直接作为前缀修饰对象实例,自动判断作用域,自动释放。这样也会存在的问题,就是可能因为考虑不充分导致作用域变得不再可控,解决方法是增加花括号定义代码块作为可控的作用域。

  • 文件范围的namespace声明:就是专门一行声明命名空间,减少一层括号的嵌套。

  • 可空类型:通过类型后加?声明,应用时需要作空检查,不然会有警告信息。通过变量后加!也可以避免警告,但这样也就会承担相应的风险。可空类型的原理是编译器为变量添加了代表可空的属性,利用反射可以获取判断。

  • 记录类型:它作为一种不可变类型,能够降低一些只读数据的性能消耗并且提升安全性。它使用record声明,本质是一种语法糖,它会在内部实现相应的方法,由此可以进行实例与实例之间的比较,虽然它们是不同的引用,但数据相同就被视为相等。实例化以后,它的属性就不可以再改变,当然它也能声明可变属性,但与其本意相违背,不建议使用。因为记录类型是与数据相关的数据结构,有时存在两个实例间数据条目仅有一两条相异的情形,可以使用with关键字在前者的基础上为后者赋值。

3 异步编程

3.1 异步编程是什么?

  • 一种更合理地调度线程的编程方式,对比于同步编程。

3.2 为什么会有异步编程?

  • 计算机的资源是有限的,充分利用它的计算资源非常重要。在同步编程下,因为同步而带来的等待会占用额外的线程,因此导致计算机的并发能力受限。而在异步下会将线程返还给线程池(如果调用的异步函数开新线程的话),然后异步函数执行之完后再回调到原来的调用处,通过这种方式节省线程资源。直观理解,同步会需要两个线程,而异步只用一个线程。

3.3 异步编程适用于什么场景?

  • 对于调用的函数,用户不关心或不需要立即拿到结果的时候,采用异步编程的方式是适合的。对于有并发要求的场景,异步同样是提升并发优势的要素。

3.4 异步编程优缺点?

  • 优点是并发,缺点是单个任务的处理时间会有一定程度的增加。

3.5 常见用法,注意事项

  • 从本质上讲,awaitasync都是语法糖,await用来切块和解析,aysnc用来标识和包装。

  • 包装、解析:异步编程通常来说是有返回值的,如果异步方法有async关键字,那么return T会自动以Task<T>作为包装。如果不用async修饰,那么需要直接构建此形式,如Task.FromResult("hello")await的作用是将Task<T>解析为T。如果确实没有返回值,可以返回Task类型,即Task.CompletedTask

  • 切块:和异步的实现原理有关,利用await来对源码分段,以实现状态机。

  • 标识:有async关键字的异步函数的内部,才能await关键字。

  • 注意1:调用异步方法时,如果不用await关键字,不会将线程还给线程池,而兵分两路,不等异步方法执行完毕,直接向下执行。

  • 注意2:异步方法也可以不用async修饰,但只要其返回值是Task相关类型,就可以通过await调用。

3.6 底层原理

  • 异步实现的方式依赖于通过await将源码分区为相应数量的段,然后以状态机的形式在这些段中切换。看源码可知为此会新建一个类,异步中涉及的局部变量会被存储为全局变量,所以切换是没有障碍的。

4 LINQ

4.1 LINQ是什么?

  • LINQ,也就是Language Integrated Query,语言集成查询。和SQL语句的查询逻辑类似。配合EF Core,可以很好地实现复杂形态数据的查询,非常方便。

4.2 为什么会有LINQ

  • 简化数据访问的流程,清晰数据访问的代码。

4.3 LINQ适用的场景?

  • .NET下,适应所有与数据相关的场景,除非有特殊的要求。

4.4 LINQ优缺点?

  • 优点:简单、统一、清晰。

  • 缺点:可能在一些情况下访问数据的效率会成为问题。

4.5 LINQ常见用法

4.5.1 lambda表达式
  • 就是一种简化的匿名函数的写法。

  • 委托。对于参数类型相容的方法,声明一个委托实例可以指向这些方法。可以不用自定义委托类型,使用自带的ActionFunc委托已经足够了,它们都是泛型委托,最多可以支持16个参数。前者没有返回值,后者有返回值。

  • 匿名函数。非常规形式定义的函数,直接在语句中定义,它没有名字。委托可以指向普通函数,也可以指向匿名函数。利用delegate关键字定义。

  • lambda表达式,实际就是去掉delegate关键字,换成=>关键字定义的匿名函数。

  • 共性与简化:不论是delegate还是=>定义的匿名函数,它们的常规形态都需要用()圈参数,{}圈语句。lambda表达式的创意是,可以去掉return关键字如果只有一行代码。如果只有一行代码可以省略{}。只有一个参数可以省略()。总之,lambda表达式让我们编写匿名函数变得更简单。

4.5.2 LINQ相关的扩展方法
  • LINQ的关键就在于其对于实现IEnumerable<T>接口的类的扩展方法,这些扩展方法来源于System.Linq里的静态类。

  • 扩展方法,来源于语言的支持,可以实现不修改现有类,却能为它添加新的方法。具体应用时,需要写一个static的扩展类,然后在里面写一个static的方法,它的参数需要包含需要扩展方法的类,并且以this关键字修饰,然后扩展方法就可用了。System.Linq里的一些静态类正是在干这样的事。

4.5.2.1 数据过滤Where()方法
  • 参数是一个lambda表达式,其对应的委托是Func<TSource,bool> predicate,即这个匿名函数的返回值为bool类型,用来代表某个数据是否满足要求。
4.5.2.2 获取数据条数Count()方法
  • 参数同Where()方法。需要注意如果数据条数多过int所能表达的限制(21亿),应采用LongCount()方法。
4.5.2.3 判断是否至少有一条满足的数据Any()方法
  • 参数同Where()方法。Ang()方法的好处是如果找到一条数据就会结束查找,性能相对Count()方法会好一些。当然这时针对两者都满足要求的场景。
4.5.2.4 关于获取一条数据的方法
  • Single():必须只有一条数据。

  • SingleOrDefault():如果不是一条数据,也可以返回默认值。

  • First():第一条数据。

  • FirstOrDefault():如果连一条数据都没有,也可以返回默认值。

4.5.2.5 排序
  • OrderBy():正序,由小到大。

  • OrderByDescending():倒序,由大到小。

  • 匿名方法返回值为需要排序的数据本身。

4.5.2.6 切割结果
  • Skip():跳过多少个。

  • Take():需要多少个。

4.5.2.7 聚合函数
  • 即代表一系列的计算数据的特征的方法。

  • Max():找最大的

  • Min():找最小的

  • Average():求平均值

  • Sum():求和

  • Count():求个数

4.5.2.8 分组方法GroupBy()
  • 利用IGrouping<TKey,TSource>接口实现,IGrouping继承自IEnumerable,它包含了一个TKey参数存储用来分组的数据,而用TSource继续存储原来的数据。
4.5.2.9 投影方法Select()
  • 可以直接返回现有的数据,也可以利用new关键字重新构建一个自定义的数据格式。
4.5.2.10 集合转换
  • ToArray():正常得到的都是IEnumerable<T>类型,需要的话也可以转换为数组类型。

  • ToList():同上,需要的话也可以转换为List<T>类型。

4.6 LINQ的其它写法
  • LINQ语句也可以写为类SQL语句的形式,但丧失了链式表达式的优势,既不清晰也不简单,一般不用。

5 结束

  • 直观理解的结果,似乎会导致对于具体的编码相对生疏。但我相信,技术的核心,在于理解它的价值并将它用好。在大家笑谈程序员的本质就是Ctrl+C/V的时候,我还是想选择当个明明白白的复读机。
posted @   吾倚风  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示