从今天开始,在这里记录重新学习 C# 的学习笔记。
导语
之前曾经自学过一段时间的 C# ,也写过一些 WinForm 的小工具。个人认为 C# 是我所见过的用法最为优雅,使用起来最为舒服的语言,因此便对 C# 喜爱有加。但后来由于微软的固步自封,使得 C# 只能在 Windows 平台上发挥作用,而随后,开源跨平台成为历史发展的趋势。因此不得已只好放弃。
虽然有点晚,但是微软终于是迷途知返。首先出现了开源跨平台的 .NET Core 项目,近来听闻微软又打算将 .NET Core 和 .NET Framework 合二为一成为一个完全开源跨平台的 .NET 项目,即 .NET 5。因此决定重新再学习以下 C# 和 ASP.NET 平台,用它来主力开发 Web 项目。便决定将学习过程中的笔记和总结卸载这里。
本次学习使用的书籍是《C# 7.0 in a Nutshell》。在这篇文章写成之时,C# 8.0 其实已经面试很长时间了,但无奈市面上包含 C# 8.0 的书籍很少,好在 C# 8.0 和 7.0 之间的差异不是很大,因此便先使用这本书吧。
PS:我使用的是英文版,原因是我没有找到这本书的中文版资源。。。
写在前面
说到 .NET 的学习,相信很多人应该听过著名的 Github 项目 developer-roadmap 和 AspNetCore-Developer-Roadmap,上面列出来了非常全面的 .NET 和 ASP.NET 的学习路线。以我目前的精力,应该是没有办法沿着路线一点一点走下去了。但是还在这里写一下,第一步的计划是学完 C# 语言和 ASP.NET 框架(这里当然指的是 Core ),以及一些基础的 Entry Framework 的知识。
好了,闲话不多说,马上进入正题吧。
C# 语言
关于 C# 的定义,书中给出的第一句话是:
C# 是一门通用的,类型安全的,面向对象的变成语言。
这应该是一个盖棺性质的定论了。讲出了 C# 最想突出的特性,即通用型,类型安全和面向对象。 C# 语言的目标,或者说诞生的目的,是为了提高生产力。为了达到这个目的,C# 对以下三个方面进行了平衡:
- 简洁性
- 表达能力
- 性能
C# 的通用性
C# 被设计为一个平台无关的,也就是跨平台的语言。但是由于种种原因,其长期服务于 Windows 这一个平台。但现在可以借助 .NET Core 项目,让 C# 语言实现跨平台,可以支持 Windows,Linux,MacOS,iOS 和 Androis 这五大常用平台。
C# 的面向对象特性
C# 作为一个面向对象的语言,它有着丰富的功能来更好的支持面向对象特性。接下来我们主要从几个方面阐述以下 C# 语言的面向对象特性。
统一的类型系统
C# 拥有一个统一的类型系统,它表现在 C# 的所有类型,无论是原始类型还是用户自定义类型,都是继承同一个基础类型,即 object
类型。因此所有类型都具有某些相同的原始功能。
例如,所有的类型都具有 ToString()
这个方法,它将对象转换成对应的字符串。
类( class )和接口( interface )
C# 与 C++ 等语言不同的是,C# 语言的类不支持多继承,因此一个子类无法从多个基类中派生,也无法具有多个类的特性。但 C# 并非不能达成这个目的,而是采用一个更为优雅的方法,引入了接口。
在这里我们不详细的讲什么是接口,只是说明接口的基本信息。接口只声明函数而不定义函数的实体,类似于 C++ 中的纯虚函数,但是与类不同的是,接口只能够拥有这些“纯虚函数”,因此它不能实例化对象,而只能够被其他的类继承。一个类可以继承于多个接口。
比如,
- 人可以完成呼吸这个动作,这里呼吸就是一个接口,人这个类继承了呼吸这个接口,呼吸的方式是使用鼻子呼吸。鱼也有呼吸这个动作,因此他也继承了呼吸这个接口,呼吸的方式是用腮呼吸。
- 人有行进这个动作,而鱼没有,因此人继承了行进这个接口,而鱼没有继承。
属性( property ),方法( method )和事件( event )
在大部分的面向对象编程语言中,所有的函数都是方法。但在 C# 中,函数也可以是属性和事件。
属性是封装了一个对象状态的函数成员,它通常用来表示和操作一个对象的字段。属性和类的一个字段有些类似,但有着本质的区别。我们使用属性时往往感觉像是在使用一个字段,但其实我们是在使用关联了相关字段的方法。
事件是函数成员,它简化了对对象更新的操作。
C# 的纯洁( purity )模式
C# 语言也具有一些函数式编程的特性。函数式编程的核心是避免使用值可以改变的变量。C# 主要通过匿名函数,本地函数和 Lambda 表达式支持这个特性。
关于函数式编程,它区别于我们一般理解的命令式编程,是一种编程思想。这里的函数其实不是我们编程中理解的函数,而换成数学中的函数更为贴切。数学中的函数主要描述两个变量直接的映射关系:
y = f ( x ) y = f(x) y=f(x)
命令式编程更注重于程序执行过程中的命令,或者说执行步骤,而函数式编程则着眼于不同变量之间的映射关系。
C# 的类型安全
类型安全指的是数据实例只能够按照定义好的方式相互作用。它保证了数据内部信息的完整性。C# 支持静态类型。这意味着这些数据的类型在编译阶段就被确定类,并且不可更改。因此许多关于类型的错误能够在编译阶段被发现。
C# 也可以通过 dynamic
关键字来支持动态类型,这个类型依然会在编译阶段被确定。
C# 是一个强类型的语言,这就是说你不能将一个 int
类型的变量传给一个参数是 string
类型的函数。
C# 的内存管理
C# 编译器会将一个垃圾回收器( garbage collection )作为程序的一部分一起运行。垃圾回收器会自动回收那些不再被需要的内存。一段内存被判定为不再被需要的标准时,这段内存没有被活跃的引用变量指向。
根据我的经验,内存不会被马上回收,而是由垃圾回收器选择时机进行回收。
公共语言运行时
最后来简要介绍一下公共语言运行时( Common Language Runtime or CLR )。
公共语言运行时是 .NET 框架的基础。所有的 .NET 框架的语言都是在它的基础上运行的。因此 C# 语言在编译阶段不会被直接编译成机器语言,而是被编译器编译成一种中间语言( Intermediate Language or IL)。
公共语言运行时在程序执行的时候加载中间语言 IL,然后在运行的时候采用即时( Just in Time or JIT )的方式将他们翻译成对应架构的机器语言,然后执行程序。