C# 0: 语言参考(快速参考手册)

本文最后更新于 2021年4月4日 晚上

这系列的文章是根据微软的官方文档来写的.

概述

C# 拥有一个统一类型系统(Unified Type System), 即所有的类型, 包括原子类型, 都继承自 object 类型. 并且支持值类型引用类型.

C# 程序的入口是 Main 函数, 如下所示:

1
2
3
4
5
6
7
8
using System;
class Hello
{
static void Main()
{
Console.WriteLine("Hello, World");
}
}

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# 中可以对值类型进行 BoxingUnboxing 操作, 方法就是将值类型变量转换为 object 变量, 在转换时, 会分配一个 object 的存储空间(这个 object 对象就是 box), 然后由这个 object 持有该值(值类型变量的值会被复制到 box 中), unboxing 的过程则正好相反, 是将值从 box 中复制出来. 可以看到, 对值类型进行这两种操作是有一定开销的!

声明和表达式

这些都大同小异, 不再介绍. 主要是一些特殊的东西如下:

  • awaitasync: 语言级的异步支持

  • foreach: 集合遍历的简便写法

  • yield: 懒生成支持

  • checkedunchecked: 用于控制数学运算的溢出检测行为.

  • 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# 0: 语言参考(快速参考手册)
https://blog.rayy.top/2019/09/08/2019-2019-09-08-CSharpLanguageLearning0/
作者
貘鸣
发布于
2019年9月8日
许可协议