C# 0: 语言参考(快速参考手册)
本文最后更新于 2021年4月4日 晚上
这系列的文章是根据微软的官方文档来写的.
概述
C# 拥有一个统一类型系统(Unified Type System), 即所有的类型, 包括原子类型, 都继承自 object
类型. 并且支持值类型
和引用类型
.
C# 程序的入口是 Main 函数, 如下所示:
1 |
|
C# 中包的引入使用的是 using
关键字, 比如 using System
就是引入 System 名空间中的所有符号. 并且名空间可以包含其他名空间.
要对 C# 有整体的认识, 需要从如下方面入手:
程序结构
类型和变量
表达式
声明
类和对象
Struct
数组
接口
枚举
代理
注解
下面一一进行介绍.
程序总体结构
C# 程序中的组织概念有: program, namespace, type, member, assembly. (前面几个都比较好理解, 最后一个 assembly 是 C# 程序编译打包后的产物, 一般扩展名是 .exe
或 .dll
)
需要注意的是, 名空间中只能包含 type, C# 没有顶层函数的概念.
在 Assembly 中包含如下两个内容:
使用 IL(中间语言)表示可执行代码
使用 metadata(元数据)表示的符号信息
在 Assembly 被执行前, IL 代码会被本地的 .NET Common Language Runtime
中的 JIT
编译器编译为本地 CPU 对应的特定机器码.
类型和变量
C# 中有两大类类型:
值类型: 值类型变量存储中存储的是自己成员的实际数据.
引用类型: 引用类型变量存储中存储的是自己成员数据的引用.
不过无论是值类型还是引用类型, 它们都隐式继承自 object
类型.
C# 中值类型可细分为如下几个:
简单类型(即所有的原子类型)
枚举类型
struct
nullable 值类型(对上述值类型的可空扩展, 可以理解为 C# 中的 Optional)
C# 中引用类型可细分为如下:
class(
object
类型,string
类型, 用户自定义 class)interface
数组(使用诸如
int[]
语法创建的数组)代理(使用
delegate 返回值类型 代理类型名称(参数表)
语法声明代理, 代理即方法的引用, 也可以理解为方法的签名特征声明)
这里要注意一点, char
是值类型的, string
是引用类型的. 且 class, struct, interface, delegate 都支持泛型.
enum
类型的 case 都关联有八种整型类型的一个值.
C# 对 Optional 的支持不是很完美, 仅仅是对值类型扩展了一个 nullable 支持, 没有将引用类型和值类型对应的 Optional 统一起来像 Swift 那样处理.
C# 中可以对值类型进行 Boxing
和 Unboxing
操作, 方法就是将值类型变量转换为 object
变量, 在转换时, 会分配一个 object 的存储空间(这个 object 对象就是 box
), 然后由这个 object 持有该值(值类型变量的值会被复制到 box 中), unboxing 的过程则正好相反, 是将值从 box 中复制出来. 可以看到, 对值类型进行这两种操作是有一定开销的!
声明和表达式
这些都大同小异, 不再介绍. 主要是一些特殊的东西如下:
await
和async
: 语言级的异步支持foreach
: 集合遍历的简便写法yield
: 懒生成支持checked
和unchecked
: 用于控制数学运算的溢出检测行为.lock
: 提供互斥锁using
: 用来获取资源并使用, 在跳出using
作用域后自动调用该资源的dispose
方法从而释放资源.
上述关键字具体的用法详见官方文档.
类和对象
类的成员包括静态成员和对象成员.
如下是类中可以包含的成员:
常量
域
方法
属性
下标: 和 swift 类似, 外部可以使用
[index]
语法进行 get 或 set.事件: 表示类里面可以产生的通知, 外部的观察者就可以在事件上进行观察了.
操作符方法: 和 swift 类似
构造函数
析构函数: 很少使用, 因为内存回收机制的特点决定了在 C# 中的对象内存释放时机是不确定的. 所以一般都使用 dispose 来释放资源.
访问控制有如下几种:
public
: 无限制protected
: 继承层次中可访问internal
: 访问限制在当前的 assembly 中.protected internal
: assembly 外的子类不可访问private
: 只可在当前类内部访问.private protected
: /
在 C# 中, 静态域的行为和 swift 类似.
使用 out
关键字修饰的参数表示该参数使用引用传递.
**有如下三个关键字来修饰方法: **
virtual
: 表示该方法可以在子类中被重写override
: 表示该方法是重写的父类中的对应方法abstract
: 表示该方法是抽象方法, 没有实现, 需要在子类中提供实现. 只有抽象类才能包含抽象方法.
在 C# 中可以使用 const
声明常量, 使用 readonly
声明只读域. 单独的 get
声明只读属性.
构造函数
和其他语言有些区别的是: C# 中可以定义静态构造函数, 用于在首次加载该类的时候对类中的所有静态成员进行初始化.
故 C# 中应该也有和 JAVA 中类似的 class loader 存在.
属性
属性和域的区别: 属性和域都有关联的存储, 唯一不同的是属性可以定义访问方法, 即它们的值被读取或写入的时候, 可以进行的操作.
其他
struct
不支持自定义继承, 且它隐式继承自 ValueType
, 而 ValueType
隐式继承自 object
.
枚举可以使用类似继承的语法来定义它的 case 的值, 比如 enum MyEnum: sbyte { ... }
.
代理的作用实际上就是为了支持函数式编程, 这样可以将符合代理定义的方法作为实体对待, 从而将方法进行赋值, 或将方法作为参数传递.
注解: 略.
后续
完整的 C# 语言教程, 详见C# Programming Guide.
C# 语言实践用法, 详见Walkthroughs.
C# 语言细节参考, 详见Language Reference.