C# 知识体系相关内容知识点详解
树图思维导图提供 C# 知识体系构建脑图 在线思维导图免费制作,点击“编辑”按钮,可对 C# 知识体系构建脑图 进行在线思维导图编辑,本思维导图属于思维导图模板主题,文件编号是:6ca7c49005ce4bfd3169b2ac3bc3522e
C# 知识体系构建(第二版)思维导图模板大纲
1. 概述
没有构建 C# 知识体系,所以心里会没底
此专栏会快速过一遍 C# 核心语法特性,构建知识体系
2. 知识体系构建
需要先构建知识体系
可以获得宏观视角
学习自信
根据 C# 的版本发布顺序去构建 C# 的知识体系
包含语法特性
类(class)
功能
类可以继承
包含属性
包含方法
可以用来创建对象
面向对象
核心
建模
C、Lua 也可以面向对象
面向过程与面向对象不是对立的
面向对象更擅长设计
面向过程更擅长实现
面向对象以对象为基础单位
面向过程以函数为基础单位
引用类型 和 值类型
值类型直接存储其值
引用类型存储对其值的引用
类是引用类型
访问权限
internal
一般在打 dll 的时候作用很大,可以控制有些类不让用户访问到。
也可以配合 Unity 的 Assembly Definition 使用
private
用得不多,一般作为内部类存在
public
命名
名词,偶尔用动词
抽象类 和 接口
抽象类
抽象方法需要在子类中覆写
不能 new 一个抽象类
接口
显式实现可以控制方法的访问权限
内部类
需要在类内部创建一些只在类内部使用的对象
表达所属关系
partial 关键字
类定义代码拆分到不同的文件中
泛型类
类需要适配不同的类型的时候,可以使用泛型类
结构体(struct)
重要、常见的特性
是值类型
不能设置为 null
声明变量时,本身就有值了。
赋值是深拷贝
作为属性时,不能给结构体的成员变量直接赋值
结构体相比类,内存回收效率更高,不容易产生 gc
其他细节
在结构声明中,除非将字段声明为 const 或者 static,否则无法初始化
结构不能声明无参构造函数(没有参数的构造函数)或终结器
与类不同,无需 new 即可对结构体进行实例化
结构体可以声明具有参数的构造函数
一个结构体无法继承另一个结构体或类,自身也不可以作为基类。所有结构体都直接继承 ValueType,ValueType 继承 Object
结构体可以实现接口
内存回收
结构体与值类型一样,用完后即时回收(在函数结尾或者某一个域内)
结构体如果有引用类型的成员变量,结构体只存储其地址,回收时,也仅回收地址所占内存,而其值等待回收机制回收。
接口(interface)
隐式实现
大部分的正常实现
显式实现
必须用相应的接口来调用方法
官方用法
解决实现多个接口方法可能用重名的问题
笔者用法
降低接口方法的访问权限
其他描述
实现接口的任何类型或结构体都必须实现其所有成员。
接口类似于只有抽象成员的抽象基类。
一个类可以继承一个基类,还可以实现一个或多个接口。
接口无法直接进行实例化。
其成员由实现接口的任何类或结构体来实现。
接口可以包含事件、索引器、方法和属性。
接口不能包含方法的实现。
一个类不包含方法的实现
事件(event)
与委托的区别
只能在所声明类的内部 Invoke
属性器 不是 get 和 set 而是 add 和 remove
属性(property)
隔离内部的变化
封装性
委托(delegate)
常用委托
Action<T>
Func<T>
使用经验
Action<int> OnAgeChanged = (age)=>{}
为了防止空指针异常,可以给委托变量设置一个初始值
表达式(逻辑表达式、运算表达式等)
类型
表达式值
数值 和 字符串
调用表达式
调用方法
调用委托
查询表达式
LINQ
Lambda 表达式
其他概念
表达式树
Unity 支持有限
.Net Core 可以用
表达式主体定义
重要特性
运算符优先级
可以用括号来优先计算
语句(一般用分号结尾的算是一条语句)
定义
可以用分号为结尾的代码就是语句
类型
声明语句
表达式语句
迭代语句
跳转语句
异常处理语句
await 语句
yield return 语句
fixed 语句
lock 语句
空语句
等等
特性(也可以叫属性)(Attribute)
自定义 Attribute
继承 System.Attribute
与反射配合
小结
常见概念
表达式树
语句
类
结构体
接口
约定变成语言功能
属性
事件
委托
标记和配置
Attribute
简介
学习反射
用途
与 Attribute 配合使用
反射定义
官方
提供封装程序集、模块和类型的对象
整理过后
反射提供以下对象
封装了程序集的对象
封装了模块的对象
封装了累心的对象
笔者
反射核心就是使用各种类型(Type)相关的 API
Type 获取 API
typeof(ClassName)
object.GetType()
Type.GetType(name)
Type 对象的 API
类信息查询 API
FullName
命名空间 + 类名
Name
类名
Namespace
命名空间
等等
检测 API
IsClass
是否是类
IsAbstract
是否是抽象的
IsValueType
是否是值类型
IsEnum
是否是枚举
等等
类结构查询 API
BaseType
获取父类的类型
GetMethods
获取所有方法
GetFields
获取所有字段(默认 public 成员变量)
GetProperties
获取所有属性器
GetMembers
获取所有成员
等等
BindingFlags
Instance
搜索实例成员
NonPublic
搜索非 public
Public
搜索 public
DeclaredOnly
不搜索父类
等等
各种查询结果对象
MethodInfo 对象
MethodInfo 对象获取
GetMethod(name)
GetMethods()
方法信息查询 API
Name
返回方法名
检测 API
IsGenericMethod
是否是泛型方法
IsAbstract
是否是构造方法
IsConstructor
是否是构造方法
IsVirtual
是否是虚方法
IsPublic
是否是公开权限的
IsStatic
是否是静态的
等等
方法结构查询 API
GetBaseDefinition()
获取父类定义
ReturnType
获取返回类型
GetParameters()
获取参数对象数组(ParameterInfo[])
GetMethodBody()
获取方法体对象(MethodBodyInfo)
等等
Invoke
可以调用方法
接收方法的返回值
为方法传入参数
FieldInfo 对象
信息查询
Name
检测 API
IsInitOnly
是否是 readonly
IsPublic
是否是 公开权限的
等等
结构查询 API
FieldType
获取 Field 的类型
等等
SetValue
设置值
GetValue
获取值
MemberInfo 对象
信息查询
Name
需要转换到对应的 Info
PropertyInfo 对象
信息查询
Name
检测 API
CanRead
是否有 get
CanWrite
是否有 set
等等
结构查询 API
PropertyType
获取 Property 类型
等等
SetValue
设置值
GetValue
获取值
语法糖
is
someObj is SomeClass
someObj is BaseClass
Assembly
程序集
dll 文件
使用方式
项目引用
通过反射
Assembly.LoadFile(fullPath) 加载 dll
assembly.GetType(TypeName) 获取 类型
通过 Activator.CreateInstance(type) 创建实例
Assembly.GetExecutingAssembly()
assembly.CreateInstance(typeName) 根据反射名字创建实例
泛型
泛型类型可以最大限度地重用代码之外,还可以保护类型安全性以及提高性能
典型案例
ArrayList => List<T>
泛型的约束
可以通过 where 关键字 约束 T 的类型
经验之谈
底层、通用的代码用的多
逻辑层、UI 层 只需要会用 List、Dictionary 的程度就可以
如果自己写框架或者库,建议掌握深入一些
笔者的知识盲点
协变和逆变
typeof(Base<,>)
分部类型
partial 关键字
将一个类的定义拆分到不同的文件中
常见用法
ViewController 拆分
SomeUI.cs
SomeUI.Designer.cs
API 声明拆分
Observable.XXX.cs
Observable.YYY.cs
匿名方法
C# 1.0
action = OnValueChanged
只能通过方法注册委托
C# 2.0
action = delegate(int value) { Debug.Log(value); }
可以通过匿名方法注册委托
可以为 null 的值类型
int? number = null
值类型比较难以判断是否初始化,有了可空值类型的支持就比较容易了
迭代器
迭代器方法
返回类型为
IEnumerator
需要作为一个类的 GetEnumerator 方法
IEnumerable
IEnumerator<T>
需要作为一个类的 GetEnumerator 方法
IEnumerable<T>
可以直接或间接地通过 foreach 进行遍历
Yield 关键字
yield 实际上是一个语法糖
Yield 翻译成 il 后的代码类似是一个 状态机
迭代器理解
IEnumerator 使用
foreach 类似实现
实现
迭代器模式与 IEnumerable
迭代器模式
提供一种方法顺序访问一个集合对象中的各个元素,又不暴露该对象的内部表示
IEnumerable
IForeachable
yield return 的值可以直接通过 foreach 得到
yield 同等实现
Coroutine 的原理
Coroutine 的原理就是每一帧调用 IEnumerator 的 MoveNext
逆变与协变
协变就是父接口的泛型是只读的,用 out 关键字修饰即可
现编就是父接口的泛型是只写的,用 in 关键字继续即可
如果无法确定父接口的泛型是只读还是只写的,只能确保同泛型类型之间发生协变。比如:IEnumerable<string> a = new List<string>();
getter/setter 单独可访问性
单独给 get 或者 set 设置访问权限
方法组转换(委托)
方法组可以直接给委托变量赋值,而不用进行委托的包装
静态类
不能创建实例的类
静态构造
被访问时调用构造
委托推断
可以推断一个方法组的返回值和参数是否匹配
自动实现的属性
匿名类型
查询表达式(LINQ)
表达式
表达式树
扩展方法
隐式类型本地变量
分部方法
对象和集合初始值设定项