API | 说明 |
---|---|
Console.WriteLine |
输出文本并换行(支持占位符,如 WriteLine("{0}", value) )。 |
Console.Write |
输出文本不换行。 |
Console.ReadLine |
读取一行输入,返回字符串(用户输入以回车结束)。 |
Console.ReadKey |
读取单个按键,返回 ConsoleKeyInfo (可捕获键盘事件)。 |
分类 | 类型 | 默认值 |
---|---|---|
有符号整型 | sbyte (8位)、short (16位)、int (32位)、long (64位) |
0 |
无符号整型 | byte (8位)、ushort (16位)、uint (32位)、ulong (64位) |
0 |
浮点数 | float (单精度)、double (双精度)、decimal (高精度) |
0.0 |
布尔/字符 | bool (true /false )、char (单字符,如 'A' ) |
false /\0 |
字符串 | string (引用类型,不可变) |
null |
const 类型 名称 = 值;
(如 const float PI = 3.14f;
)。符号 | 含义 | 场景 |
---|---|---|
\' |
单引号 | 字符串中包含单引号(如 'Hello' )。 |
\" |
双引号 | 字符串中包含双引号(如 "World" )。 |
\n |
换行符 | 换行(如 str = "Line1\nLine2" )。 |
\\ |
反斜杠 | 文件路径(如 C:\\Folder\\File.txt )。 |
\t |
制表符(Tab) | 对齐文本(如 Name\tAge )。 |
\b |
退格符 | 回退一格(如 12\b3 → 13 )。 |
\a |
警报音 | 触发系统提示音(慎用)。 |
double → float → 整数(无符号/有符号) → char
;decimal → 整数 → char
。
(string
、bool
不参与隐式转换)
方法 | 说明 |
---|---|
(类型) 值 |
括号强转(如 (int)3.14 ) |
int.Parse(字符串) |
字符串转 int (失败抛异常) |
Convert.ToInt32(值) |
任意类型转 32 位整数 |
ToString() |
对象转字符串(重写自定义) |
类型 | 运算符 | 说明 | 优先级(高→低) |
---|---|---|---|
算术运算符 | + - * / % |
加减乘除取余(例:7 % 3 = 1 ) |
乘除取余(* / % )> 加减(+ - ) |
赋值运算符 | = += -= *= /= %= |
赋值或复合运算(例:a += 2 → a = a + 2 ) |
最低 |
比较运算符 | > < >= <= == != |
比较结果为 bool (例:3 > 2 → true ) |
高于逻辑运算符(除 ! 外) |
逻辑运算符 | ! && || |
逻辑非、与、或(短路特性:&& 左假则右不执行,|| 左真则右不执行) |
! > && > || |
位运算符 | & | ^ ~ << >> |
位运算(例:5 << 1 = 10 ,5 & 3 = 1 ) |
高于逻辑运算符(仅 ! 例外) |
三目运算符 | 空位 ? 空位 : 空位 ` | bool类型 ? bool类型为真返回内容 : bool类型为假返回内容; |
语句 | 语法 | 特点 |
---|---|---|
if |
if (条件) { 代码 } |
单分支,条件为 true 执行。 |
if...else |
if (条件) { ... } else { ... } |
双分支,条件为 false 执行 else 。 |
switch |
switch (变量) { case 常量: 代码; break; } |
多分支,case 需 break (支持贯穿)。 |
语句 | 语法 | 执行顺序 |
---|---|---|
while |
while (条件) { 循环体 } |
先判断,后执行(可能不执行)。 |
do...while |
do { 循环体 } while (条件); |
先执行,后判断(至少一次)。 |
for |
for (初始; 条件; 增量) { 循环体 } |
固定次数,适合已知范围。 |
关键字 | 作用 | 适用场景 |
---|---|---|
break |
跳出当前循环或 switch |
提前终止流程。 |
continue |
跳过本次循环,继续下次 | 忽略后续代码,直接进入下次循环。 |
块 | 说明 | 是否必须 |
---|---|---|
try |
包含可能抛出异常的代码。 | 是 |
catch |
捕获异常(可指定 Exception e 获取错误信息)。 |
是(至少一个) |
finally |
无论是否异常,最终执行(释放资源)。 | 否 |
示例结构
try { /* 风险代码 */ }
catch (Exception e) { /* 处理异常 */ }
finally { /* 清理资源 */ }
分类 | 规则/特性 | 示例/说明 | 高频场景 |
---|---|---|---|
声明 | enum E_Type { A, B=5, C } |
首项默认0,后续递增;自定义值从指定项开始 | 状态标识(如E_PlayerState.Idle ) |
变量赋值 | E_Type var = E_Type.B; |
直接赋值枚举项 | 逻辑判断(if (var == E_Type.A) ) |
类型转换 | 枚举→int:(int)var 字符串→枚举: (E_Type)Enum.Parse(typeof(E_Type), "B") |
int num = (int)E_Type.A; // 0 |
配置表映射、日志输出 |
注意 | 声明在namespace/class ,禁止函数内声明;避免魔数依赖 |
反例:不用int state = 0 ,改用枚举 |
提高代码可读性 |
类型 | 声明语法 | 索引方式 | 长度 | 内存 | 适用场景 |
---|---|---|---|---|---|
一维数组 | int[] arr = {1, 2, 3}; |
arr[索引] (0-based) |
arr.Length (固定) |
连续 | 线性数据(分数、ID列表) |
二维数组 | int[,] arr2D = {{1,2}, {3,4}}; |
arr2D[行, 列] |
arr2D.GetLength(0) (行数)GetLength(1) (列数) |
连续(按行存储) | 规则表格(棋盘、矩阵) |
交错数组 | int[][] jagged = { new int[2], new int[3] }; |
jagged[行][列] |
jagged.Length (行数)jagged[行].Length (每行长度) |
不连续(子数组独立) | 不规则数据(动态行列表) |
维度 | 值类型 | 引用类型 | 特殊引用(string) |
---|---|---|---|
存储位置 | 栈(直接存值) | 堆(存值)+ 栈(存地址) | 堆(存值)+ 栈(存地址) |
赋值行为 | 深拷贝(独立,它变我不变) | 浅拷贝(共享地址,它变我也变) | 伪深拷贝(新建地址,它变我不变) |
默认值 | 非null (如int=0 ) |
null |
null |
典型示例 | int 、bool 、enum 、struct |
int[] 、class 、object |
string |
内存管理 | 系统自动分配/释放(栈) | 手动new ,依赖GC(堆) |
频繁new ,需StringBuilder 优化 |
方法 | 说明 |
---|---|
str + str2 |
拼接字符串 |
string.Format |
格式化字符串 |
str.Length |
获取字符串长度 |
str.IndexOf("子串") |
查找子串位置(未找到返回 -1) |
str.Substring(start, len) |
截取子串 |
StringBuilder
:高频拼接时使用(需 using System.Text;
)。
Append()
(追加)、Replace()
(替换)、ToString()
(转字符串)。特性 | ref | out |
---|---|---|
核心 | 传递变量“内存地址”,双向修改 | 强制“输出参数”,必须方法内赋值 |
初始化 | 必须先赋值(传入前有值) | 无需初始化(方法内必须赋值) |
场景 | 交换变量、复杂计算修改原值 | 返回多个结果(替代 return) |
示例 | Swap(ref a, ref b) |
TryParse(out int result) |
特性 | params | 默认值 |
---|---|---|
核心 | 接收任意数量同类型参数 | 调用时可省略参数 |
规则 | 只能 1 个,且是最后一个参数 | 必须在参数列表末尾 |
场景 | 不定数量参数 | 常用参数简化调用 |
示例 | Sum(1,2,3) |
Attack(damage: 100) |
核心规则 | 示例 |
---|---|
参数数量不同 | Attack(int d) / Attack(int d, bool crit) |
参数类型不同 | Attack(float d) / Attack(string msg) |
不能仅靠返回值重载 | ❌ 无效 int Attack() {} vs void Attack() {} |
编译器匹配逻辑 | 优先精确匹配 → 隐式转换 |
核心要素 | 示例(阶乘) | 反例(无终止) |
---|---|---|
终止条件 | if(n==0) return 1; |
❌ Loop(); 无限递归 |
状态逼近 | n * Factorial(n-1) |
每次调用趋近终止条件 |
栈溢出风险 | 慎用深层递归(>1000 层) | 改用迭代优化性能 |
特性 | 结构体(值类型) | 类(引用类型) |
---|---|---|
存储位置 | 栈(轻量,直接存值) | 堆(存值)+ 栈(存地址) |
继承 | 不能继承类,可实现接口 | 支持单类继承 + 多接口 |
构造函数 | 必须初始化所有成员,无默认无参 | 可选无参,成员默认初始化(如int=0 ) |
赋值行为 | 深拷贝(独立,修改互不影响) | 浅拷贝(共享地址,修改联动) |
默认值 | 非null (如int=0 ,bool=false ) |
null (未初始化时) |
适用场景 | 轻量数据(坐标Point 、颜色Color ) |
复杂对象(玩家Player 、场景Scene ) |
访问修饰符 | 访问权限 | 说明 | 默认使用场景 |
---|---|---|---|
public |
公共的,自己(内部)和别人(外部)都能访问和使用 | 该修饰符修饰的成员可在任何地方被访问,常用于暴露类的功能给外部调用。 | 当你希望类或成员能被项目内所有代码自由访问时使用,比如一些工具类的公共方法。 |
private |
私有的,自己(内部)才能访问和使用,不写默认为 private |
用它修饰的成员只能在声明该成员的类内部被访问,用于隐藏类的实现细节,防止外部直接修改。 | 当你想把类的某些实现细节隐藏起来,只在类内部使用时,如类的私有字段和方法。 |
protected |
保护的,自己(内部)和子类才能访问和使用 | 此修饰符修饰的成员能在声明该成员的类及其派生类中被访问,常用于实现继承体系中的代码复用与保护。 | 当你希望类的某些成员可以被子类访问,但又不想让外部直接访问时,比如基类中的受保护方法,子类可以继承和重写。 |
internal |
内部的,同一个程序集(通常是同一个项目)内可以访问 | 用 internal 修饰的成员能在定义它的程序集(项目)内被访问,在不同程序集里无法访问,用于限制访问范围在项目内部。 |
当你希望类或成员只能在当前项目中被访问,而对其他项目隐藏时,比如项目内部的辅助类和工具方法。 |
类别 | 详情 |
---|---|
构造函数 | 概念:实例化对象时调用的初始化函数,未自定义则有默认无参构造。 规则:无返回值,函数名与类名相同,常用 public 修饰,支持重载,可用 this 指代当前对象。注意:实现有参构造会覆盖默认无参构造。 特殊用法:用 this(参数列表) 重用构造函数代码,先执行 this 后构造函数,再返回当前构造函数。 |
析构函数 | 概念:引用类型堆内存回收时调用,C# 有 GC,极少使用,Unity 开发基本不用。 语法: ~类名() { /* 代码 */ } |
垃圾回收机制(GC) | 概念:遍历堆上对象,回收无引用的垃圾对象。 算法:采用分代算法,分 0、1、2 代内存,新对象在 0 代,回收时先标记可达对象,再释放未标记对象并搬迁可达对象,大对象(>85000 字节)为 2 代,不搬迁压缩。 注意:GC 仅处理堆内存,引用类型堆内存由 GC 管理,值类型栈内存由系统自动管理。 手动触发: GC.Collect(); ,一般在 Loading 场景时用,不常调用。 |
类别 | 使用规则 | 核心说明 |
---|---|---|
静态成员 | static 修饰,属于类本身,所有实例共享,通过类名.成员直接访问(无需实例化)。 |
用于全局状态(如计数器)或工具方法(如 Math.PI ),避免重复实例化。 |
静态类 | static 修饰,仅含静态成员,不可实例化(无构造函数),强制所有成员为静态。 |
封装无状态的工具逻辑(如 FileHelper ),提升代码规范性(如 LogHelper.Info() )。 |
静态构造函数 | 无访问修饰符,无参数,与类名相同,首次使用类或其静态成员时自动执行(CLR 触发)。 | 初始化静态成员(如加载配置文件),仅执行一次,无需手动调用。 |
类别 | 使用规则 | 核心说明 |
---|---|---|
成员属性 | 通过 get /set 封装字段,控制读写逻辑(如校验值范围),支持自动属性(public int Age { get; set; } )。 |
隐藏字段细节,实现数据验证(如set { if (value>0) _age=value; } ),提升封装性。 |
索引器 | 用 this[索引] 定义,支持对象通过索引访问(如obj[0] = value ),可重载参数类型(如字符串索引)。 |
模拟数组行为,增强对象易用性(如Dictionary[key] ),索引器本质是特殊属性。 |
拓展方法 | 在静态类中定义,首个参数用 this 修饰目标类型(如public static void Ext(this string s) ),扩展现有类型功能。 |
为非自定义类型添加方法(如"abc".IsValid() ),避免继承或修改原始代码。 |
运算符重载 | 用 operator 关键字为自定义类型重定义运算符(如+ 、== ),需成对实现(如== 和!= )。 |
让自定义类型支持内置运算符(如Vector2 a + b ),提升代码可读性(替代Add() 方法)。 |
类别 | 子类别 | 使用规则 | 核心说明 |
---|---|---|---|
内部类 | 内部类 | 在外部类内部定义,可访问外部类所有成员(包括私有成员)。 | 封装紧密关联的辅助类,增强代码内聚性(如事件处理器嵌套在主类中)。 |
分部类 | 分部类 | 用 partial 修饰类,允许将类定义拆分到多个文件(同一命名空间)。 |
适合大型类或自动生成代码(如UI设计器+手工逻辑),提升协作效率。 |
继承 | 里氏替换原则 | 子类对象可无缝替换父类对象,程序行为不变(子类行为兼容父类)。 | 确保继承体系的稳定性,避免子类破坏父类契约(如不缩小方法访问权限)。 |
继承中的构造函数 | 子类构造函数默认调用父类无参构造;若父类无无参构造,需显式用 base(参数) 调用。 |
保证父类成员正确初始化(如 class Child : Parent { public Child() : base(10) { } } )。 |
|
多态 | virtual |
父类方法声明为虚方法,允许子类重写(非强制)。 | 定义可扩展的方法模板(如 public virtual void Draw() { } )。 |
override |
子类用 override 重写父类 virtual 方法,实现差异化逻辑。 |
子类定制父类行为(如 public override void Draw() { 绘制圆形 } )。 |
|
base |
子类中通过 base.成员 调用父类方法/属性,复用父类逻辑。 |
在重写方法中保留父类行为(如 base.Draw(); 补充子类逻辑 )。 |
|
密封类 | 密封类 | 用 sealed 修饰类,禁止被继承(密封类不能有子类)。 |
固定类的实现,防止被修改(如工具类 sealed class MathHelper { } )。 |
密封方法 | 密封方法 | 子类用 sealed override 修饰重写方法,禁止孙类进一步重写。 |
固定关键逻辑(如 public sealed override void Finalize() { } )。 |
类别 | 使用规则 | 常用 API | 作用说明 | 核心说明 |
---|---|---|---|---|
万物之父(object ) |
object 是所有类型的基类,任何类型可隐式转 object 类型。 |
ToString() |
将对象转换为字符串,默认返回类型名,可重写增强可读性 | 作为基类,提供通用方法,方便对不同类型对象进行操作。 |
Equals() |
比较两个对象是否相等,默认比引用,可重写实现值比较 | |||
GetHashCode() |
返回对象哈希码,重写 Equals() 时通常也要重写此方法 |
|||
GetType() |
动态获取对象运行时的类型信息 | |||
MemberwiseClone() |
实现对象浅拷贝,值类型独立复制,引用类型共享引用 | |||
ReferenceEquals() |
判断两个对象引用是否指向同一位置,值类型通常返回 false |
|||
装箱 | 值类型转引用类型(object 类型)。 |
直接赋值 | 使值类型可当作引用类型处理 | 使值类型可用于需引用类型的场景。 |
拆箱 | 引用类型(object 类型)转原值类型,需显式转换。 |
强制类型转换 | 将装箱的值类型对象还原为原始值类型 | 将之前装箱的值类型对象还原。 |
类别 | 子类别 | 使用规则 | 常用 API | 核心说明 |
---|---|---|---|---|
抽象类和抽象方法 | 抽象类 | 用 abstract 修饰,不能实例化,只能作为基类被继承。可包含抽象方法和非抽象方法、字段等。 |
abstract |
为子类提供通用的属性和方法框架,强制子类遵循特定的设计,适用于有一定共性实现的类体系。 |
抽象方法 | 用 abstract 修饰,无方法体,子类必须重写。 |
abstract |
定义子类必须实现的行为,实现多态性。 | |
接口 | 接口 | 用 interface 定义,只包含方法、属性、索引器和事件的声明,没有字段,成员默认是 public 且不能有访问修饰符,实现类必须实现所有成员。 |
interface |
定义一组行为规范,允许类实现多个接口,增强代码的灵活性和可扩展性,适用于不同类之间需要实现相同行为的场景。 |
public
且不能有访问修饰符。特性 | 抽象类(abstract class ) |
接口(interface ) |
---|---|---|
成员变量 | 支持 | 不支持 |
构造函数 | 支持(子类调用 base ) |
不支持 |
继承 | 单继承 | 多继承 |
实现约束 | 抽象方法必须实现,虚方法可选 | 所有成员必须实现 |
场景 | 对象模板(如 Animal ) |
行为规范(如 IFly ) |
string
常用方法方法 | 作用 | 示例代码 |
---|---|---|
[index] |
通过索引获取指定位置字符,类似数组索引器。 | string string2 = "林文韬"; Console.WriteLine(string2[0]); // 林 |
ToCharArray() |
将字符串转为 char 数组。 |
char[] chars = string2.ToCharArray(); Console.WriteLine(chars[1]); // 文 |
Format() |
字符串拼接,有多个重载。 | string string3 = string.Format("{0}{1}{2}", 183, 1834, 8848); Console.WriteLine(string3); // 18318348848 |
IndexOf() |
正向查找字符或字符串位置,返回首个匹配字符索引,未找到返回 -1。 | string string4 = "我是林文韬"; int index = string4.IndexOf("林"); Console.WriteLine(index); // 2 |
LastIndexOf() |
反向查找字符串位置,返回最后匹配的首个字符索引,未找到返回 -1。 | string string5 = "我是林文韬林文韬"; index = string5.LastIndexOf("林文韬"); Console.WriteLine(index); // 5 |
Remove() |
移除指定位置后的字符,有两个重载,原字符串不变,返回新字符串。 | string string6 = "我是林文韬林文韬"; string6 = string6.Remove(4); Console.WriteLine(string6); // 我是林文 |
Replace() |
替换指定字符串,原字符串不变,返回新字符串。 | string string7 = "我是林文韬林文韬"; string7 = string7.Replace("林文韬", "老炮儿"); Console.WriteLine(string7); // 我是老炮儿老炮儿 |
ToUpper() 和 ToLower() |
大小写转换,原字符串不变,返回新字符串。 | string string8 = "linwentaozhendeshuai"; string8 = string8.ToUpper(); Console.WriteLine(string8); // LINWENTAOZHENDESHUAI |
Substring() |
字符串截取,有两个重载,原字符串不变,返回新字符串,需注意越界问题。 | string string9 = "林文韬林文韬"; string9 = string9.Substring(2); Console.WriteLine(string9); // 韬林文韬 |
Split() |
字符串切割,返回 string 数组。 |
`string string10 = "1_1 |
StringBuilder
常用方法方法 | 作用 | 示例代码 |
---|---|---|
Append() |
在尾部直接拼接字符串。 | stringBuilder1.Append("4444"); Console.WriteLine(stringBuilder1); // 1231231234444 |
AppendFormat() |
按指定格式在尾部拼接字符串。 | stringBuilder1.AppendFormat("{0}{1}", 100, 999); Console.WriteLine(stringBuilder1); // 1231231234444100999 |
Insert() |
在指定索引位置插入字符串。 | stringBuilder1.Insert(1, "林文"); Console.WriteLine(stringBuilder1); // 1林文231231234444100999 |
Remove() |
移除指定索引开始的指定长度字符。 | stringBuilder1.Remove(0, 10); Console.WriteLine(stringBuilder1); // 234444100999 |
[index] |
索引器,可 get 和 set 字符。 |
Console.WriteLine(stringBuilder1[1]); // 3 stringBuilder1[0] = 'A'; Console.WriteLine(stringBuilder1); // A34444100999 |
Replace() |
替换指定字符串,直接修改原对象。 | stringBuilder1.Replace("1", "林"); Console.WriteLine(stringBuilder1); // A34444林00999 |
Clear() |
清空字符串。 | stringBuilder1.Clear(); Console.WriteLine(stringBuilder1); // 输出空 |
Equals() |
判断是否和某字符串相等。 | stringBuilder1.Append("林文真的帅"); if (stringBuilder1.Equals("林文真的帅")) { Console.WriteLine("相等"); // 相等 } |
string
与 StringBuilder
对比及内存优化对比项 | string |
StringBuilder |
---|---|---|
内存使用 | 不可变,修改操作创建新对象,易产生垃圾。 | 可变,在现有对象基础上修改,节省内存。 |
灵活性 | 提供丰富操作方法,处理方便。 | 主要用于频繁拼接和修改,方法相对简单。 |
使用场景 | 需要使用独特方法处理特殊逻辑时使用。 | 需要频繁修改拼接字符串时使用。 |
本质 | 申明 | 增删查改和遍历 | 装箱拆箱 |
---|---|---|---|
object 类型数组( 不支持泛型 ) |
using System.Collections; ArrayList arrayList = new ArrayList(); |
增:Add 、AddRange 、Insert 删: Remove 、RemoveAt 、Clear 查: [] 、Contains 、IndexOf 、LastIndexOf 改: [] = 遍历: Count 、Capacity 、for 、foreach |
存储值类型时装箱,取出转换使用时拆箱 |
本质 | 申明 | 增取查改和遍历 | 装箱拆箱 |
---|---|---|---|
object[] 数组,先进后出(支持泛型) | using System.Collections; Stack stack = new Stack(); |
增:Push 取: Pop 查: Peek 、Contains 改:无(可 Clear )遍历: Count 、foreach 、ToArray 、while 弹栈 |
存储值类型时装箱,取出转换使用时拆箱 |
本质 | 申明 | 增取查改和遍历 | 装箱拆箱 |
---|---|---|---|
object[] 数组,先进先出(支持泛型) | using System.Collections; Queue queue = new Queue(); |
增:Enqueue 取: Dequeue 查: Peek 、Contains 改:无(可 Clear )遍历: Count 、foreach 、ToArray 、while 出队 |
存储值类型时装箱,取出转换使用时拆箱 |
本质 | 申明 | 增删查改和遍历 | 装箱拆箱 |
---|---|---|---|
基于键的哈希代码组织的键/值对( 不支持泛型 ) |
using System.Collections; Hashtable hashtable = new Hashtable(); |
增:Add 删: Remove 、Clear 查: [] 、Contains 、ContainsKey 、ContainsValue 改: [] = 遍历: Count 、foreach 键、foreach 值、foreach 键值对、迭代器遍历 |
存储值类型时装箱,取出转换使用时拆箱 |
本质 | 申明 | 增删查改和遍历 | 特点 |
---|---|---|---|
可变类型的泛型数组(支持泛型) | using System.Collections.Generic; List |
增:Add 、AddRange 、Insert 删: Remove 、RemoveAt 、Clear 查: [] 、Contains 、IndexOf 、LastIndexOf 改: [] = 遍历: Count 、Capacity 、for 、foreach |
基本无装箱拆箱(泛型非 object 时) |
本质 | 申明 | 增删查改和遍历 | 特点 |
---|---|---|---|
拥有泛型的 Hashtable,键/值对(支持泛型) | using System.Collections.Generic; Dictionary |
增:Add 删: Remove 、Clear 查: [] 、ContainsKey 、ContainsValue 改: [] = 遍历: Count 、foreach 键、foreach 值、foreach 键值对 |
键值对类型可自定义泛型 |
本质 | 申明 | 增删查改和遍历 |
---|---|---|
可变类型的泛型双向链表(支持泛型) | using System.Collections.Generic; LinkedList |
增:AddLast 、AddFirst 、AddAfter 、AddBefore 删: RemoveFirst 、RemoveLast 、Remove 查: First 、Last 、Find 、Contains 改:修改节点 Value 属性遍历: foreach 、节点 while 循环(从头到尾、从尾到头) |
分类 | 语法 | 示例 | 作用 |
---|---|---|---|
泛型类 | class 类名 |
class Box Box |
类型参数化,支持不同类型的相同逻辑(如容器类)。 |
泛型接口 | interface 接口名 |
interface IContainer class IntContainer : IContainer |
定义类型无关的接口契约,实现多态。 |
泛型方法 | public void 方法名 |
void Print Print("Hello"); // 类型推断 |
单个方法的类型参数化,避免代码冗余。 |
泛型占位符 | 大写字母(如T 、K 、V ),可多个 |
Dictionary |
代表未知类型,使用时指定具体类型(如Dictionary )。 |
where
)关键字约束类型 | 语法 | 约束内容 | 示例 | 注意事项 |
---|---|---|---|---|
值类型 | where T : struct |
T 必须是值类型(如int 、struct )。 |
class ValueHolder ValueHolder |
不能与 new() 组合(值类型默认有无参构造)。 |
引用类型 | where T : class |
T 必须是引用类型(如class 、interface )。 |
class RefHolder RefHolder |
可约束接口(如where T : IList )。 |
无参构造 | where T : new() |
T 必须有公共无参构造函数。 |
class Creator |
需写在 class 或 struct 之后(如where T : class, new() )。 |
基类/派生类 | where T : BaseClass |
T 必须是 BaseClass 或其子类。 |
class ShapeHolder ShapeHolder |
不能约束密封类(如string )。 |
接口 | where T : IInterface |
T 必须实现 IInterface 或其子接口。 |
class Runner Runner |
可组合多个接口(如where T : IRead, IWrite )。 |
泛型依赖 | where T : U |
T 必须是另一个泛型类型 U 或其子类。 |
class Child Child |
用于泛型类的层级约束。 |
多约束组合 | where T : class, new(), ILog |
组合多个约束(顺序固定:class /struct → new() → 接口/类)。 |
class Logger |
struct 不能与 class 共存,new() 不能单独用于 struct 。 |
分类 | 语法 | 示例 | 核心特性 |
---|---|---|---|
自定义委托 | delegate 返回值 委托名(参数列表); |
delegate int MyDelegate(int a); MyDelegate del = ReturnInt; |
定义函数类型,存储/传递方法,支持多播(+= /-= )。 |
系统委托 | Action< T1, T2 > (无返回)Func< T1, TRes > (有返回) |
Action Func |
预定义泛型委托,Action 无返回,Func 最后一个类型为返回值,支持0~16参数。 |
多播委托 | del += 方法名; del -= 方法名; |
del += Method1; del += Method2; del(); (按添加顺序执行) |
存储多个方法,执行时依次调用,移除首个匹配方法。 |
使用场景 | 回调函数、事件订阅、异步操作 | Button.Click += OnClick; |
解耦代码,实现松耦合的消息传递。 |
特性 | 委托 | 事件 | 关键区别 |
---|---|---|---|
申明 | public MyDelegate del; |
public event MyDelegate evt; |
事件需用event 关键字,限制外部访问。 |
外部操作 | 可赋值(del = null; )、调用(del(); ) |
仅可加减(evt += 方法; ),不可赋值或调用 |
安全性:防止外部随意修改/触发,仅允许类内封装调用(如if (evt != null) evt(); )。 |
存储位置 | 可作为局部变量 | 只能是类/接口的成员 | 事件是委托的“安全包裹”,强制封装。 |
典型场景 | 临时函数存储 | 按钮点击、状态变更等事件通知 | 事件驱动编程,如UI交互、游戏对象状态同步。 |
场景 | 推荐方案 | 原因 |
---|---|---|
临时回调 | Lambda 表达式 | 简洁,无需定义单独方法。 |
事件订阅 | 事件(Event) + Lambda | 安全封装,避免外部误操作。 |
需要移除的订阅 | 具名方法 + 事件 | 可通过-= 精确移除。 |
状态保持 | 闭包 | 封装私有状态,避免污染作用域。 |
多参数复杂逻辑 | 自定义委托 + 具名方法 | 提高可读性,便于调试。 |
类型 | 语法 | 示例 | 特性 |
---|---|---|---|
匿名函数 | delegate (参数) { 逻辑; } |
Action a = delegate() { Console.WriteLine("匿名"); }; |
无函数名,依附委托存在,无法单独移除(无引用)。 |
Lambda | (参数) => { 逻辑; } 或 (参数) => 表达式 |
Func |
匿名函数的简写,省略delegate ,参数类型可推断(如(x) => x*2 )。 |
参数省略 | 无参数:() => {...} 单参数: x => {...} |
Action noParam = () => Console.WriteLine(); Func |
简化代码,提升可读性,广泛用于LINQ、事件订阅。 |
缺点 | 无法指定移除(无名称) | evt += () => {...}; (只能整体清空) |
适合临时逻辑,不适合需要精确控制的场景(如需要移除特定订阅)。 |
概念 | 示例 | 核心规则 |
---|---|---|
捕获外部变量 | csharp |
内层函数(Lambda/匿名函数)引用外层作用域的变量,延长变量生命周期。 |
变量捕获 | csharp |
捕获的是变量引用而非值,最终使用循环结束时的最终值(需用int index = i; 保存当前值)。 |
使用场景 | 计数器、延迟执行、状态保持 | 封装状态,避免全局变量,如游戏中的技能冷却计时器。 |
分类 | 协变(Out) | 逆变(In) |
---|---|---|
修饰符 | out (仅接口/委托泛型) |
in (仅接口/委托泛型) |
作用 | 子类 → 父类(返回值类型) | 父类 → 子类(参数类型) |
语法 | delegate T Factory |
delegate void Action |
示例 | IEnumerable → IEnumerable |
Action → Action |
规则 | 泛型仅作返回值,遵循里氏替换 | 泛型仅作参数,参数兼容里氏替换 |
记忆 | Out 产(返回),顺(子→父) | In 消(参数),逆(父→子) |
概念 | 关键 API 与规则 | 场景 |
---|---|---|
开启线程 | new Thread(Method).Start(); (需 using System.Threading ) |
异步逻辑(如网络请求、寻路) |
后台线程 | thread.IsBackground = true; (主线程结束后自动终止) |
非关键任务(日志、心跳检测) |
线程同步 | lock (obj) { ... } (互斥锁,防竞态条件) |
共享资源(如控制台、计数器) |
优雅终止 | 标志位控制:static bool isRunning; (推荐)thread.Abort() (慎用,.NET Core 可能报错) |
避免死循环阻塞 |
线程休眠 | Thread.Sleep(1000); (当前线程休眠 1 秒) |
控制执行节奏 |
指令 | 作用 | 示例 |
---|---|---|
#define |
定义编译符号(无值变量) | #define UNITY_2024 #if UNITY_2024 ... #endif |
#if/#elif |
条件编译(平台/版本适配) | csharp |
#warning |
编译警告(不中断) | #warning "旧版本兼容代码" |
#error |
编译错误(中断编译) | #error "不支持该平台" |
#region |
折叠代码块(提升可读性) | #region 初始化代码 |
类别 | 详细内容 |
---|---|
基础概念 | 编译器:将源语言程序(如 C#、C、C++、Java 程序)翻译成目标语言程序(二进制伪机器代码程序) 程序集:编译器编译的中间产物,Windows 下为 .dll 或 .exe 文件,是代码集合 元数据:描述程序的数据,如类、函数、变量信息,存于程序集中 反射:程序运行时查看其他或自身程序集元数据,获取类、函数等信息并操作 |
反射作用 | 提高程序扩展性和灵活性,运行时获取元数据、实例化对象、操作对象和创建新对象执行任务 |
关键类及功能 | Type 类:反射基础,访问元数据,获取类型声明信息,如构造函数、方法等。获取方式有对象调用 GetType() 、typeof 关键字、Type.GetType() 方法Assembly 类:加载其他程序集,使用前需引用 System.Reflection 命名空间。加载方法有 Load 、LoadFrom 、LoadFile Activator 类:将 Type 对象快速实例化为对象, CreateInstance 方法可根据构造函数参数实例化对象 |
方法 | 作用 | 参数 | 示例 |
---|---|---|---|
GetType() | 对象获取自身 Type(运行时类型) | 无 | int a = 0; Type t = a.GetType(); |
typeof(类型) | 编译时获取类型 Type | 类型名(如 typeof(int) ) |
Type t = typeof(string); |
Type.GetType(类名) | 字符串形式获取 Type(需完整命名空间) | 类全名(如 "System.Int32" ) |
Type t = Type.GetType("CSharpTest.TestClass"); |
Assembly属性 | 获取类型所在程序集 | 无 | Console.WriteLine(t.Assembly.FullName); |
GetMembers() | 获取所有公共成员(方法、构造、字段等) | 无 | MemberInfo[] members = t.GetMembers(); |
GetMembers(BindingFlags) | 按标志获取成员(公共/私有/实例/静态) | BindingFlags.Public/NonPublic/Instance/Static |
`t.GetMembers(BindingFlags.NonPublic |
GetConstructors() | 获取所有公共构造函数 | 无 | ConstructorInfo[] ctors = t.GetConstructors(); |
GetConstructor(Type[]) | 按参数类型获取指定构造函数 | 参数类型数组(如 new Type[] { typeof(int) } ) |
ConstructorInfo ctor = t.GetConstructor(new Type[0]); // 无参构造 |
GetFields() | 获取所有公共字段 | 无 | FieldInfo[] fields = t.GetFields(); |
GetField(字段名) | 按名称获取公共字段 | 字段名(如 "j" ) |
FieldInfo field = t.GetField("j"); |
GetMethods() | 获取所有公共方法 | 无 | MethodInfo[] methods = t.GetMethods(); |
GetMethod(方法名, Type[]) | 按名称+参数类型获取指定方法(区分重载) | 方法名,参数类型数组 | MethodInfo method = t.GetMethod("Speak", Type.EmptyTypes); |
GetProperty(属性名) | 获取公共属性 | 属性名(如 "Length" ) |
PropertyInfo prop = typeof(string).GetProperty("Length"); |
GetInterface(接口名) | 获取实现的接口 | 接口名(如 "IEnumerable" ) |
Type iface = t.GetInterface("IComparable"); |
方法 | 作用 | 参数 | 示例 |
---|---|---|---|
Load(程序集名) | 加载当前目录的程序集(如 DLL/EXE) | 程序集名称(如 "CSharpTest" ) |
Assembly asm = Assembly.Load("CSharpTest"); |
LoadFrom(路径) | 加载指定路径的程序集(含路径+文件名) | 完整路径(如 @"D:\CSharpTest.dll" ) |
Assembly asm = Assembly.LoadFrom(@"CSharpTest\bin\Debug\CSharpTest.dll"); |
LoadFile(路径) | 加载指定文件(需完整路径) | 文件路径(如 @"D:\CSharpTest.dll" ) |
Assembly asm = Assembly.LoadFile(@"CSharpTest.dll"); |
GetTypes() | 获取程序集中所有类型 | 无 | Type[] types = asm.GetTypes(); |
GetType(类名) | 按类名获取程序集中的 Type(需完整命名空间) | 类全名(如 "CSharpTest.TestClass" ) |
Type t = asm.GetType("CSharpTest.TestClass"); |
方法 | 作用 | 参数 | 示例 |
---|---|---|---|
CreateInstance(Type) | 调用无参构造实例化对象 | 类型 Type(如 typeof(Test) ) |
object obj = Activator.CreateInstance(t); |
CreateInstance(Type, 对象数组) | 调用有参构造实例化对象(参数匹配构造函数) | 类型 Type,参数数组(如 new object[] { 10, "test" } ) |
object obj = Activator.CreateInstance(t, 10, "test"); |
CreateInstance(程序集名, 类名) | 动态加载程序集并实例化对象 | 程序集名,类全名 | object obj = Activator.CreateInstance("CSharpTest", "CSharpTest.TestClass"); |
构造函数调用
ctor.Invoke(null)
或 Activator.CreateInstance(t)
ctor.Invoke(new object[] { 参数1, 参数2 })
TargetInvocationException
。字段/属性操作
fieldInfo.GetValue(obj)
(实例字段需传入对象实例)fieldInfo.SetValue(obj, 新值)
(需字段为公共或使用 BindingFlags.NonPublic
)GetField("私有字段名", BindingFlags.NonPublic | BindingFlags.Instance)
获取。方法调用
methodInfo.Invoke(对象实例, 参数数组)
methodInfo.Invoke(null, 参数数组)
(string)method.Invoke(...)
)。程序集加载
LoadFrom
需完整路径(含文件名),Load
仅需程序集名(依赖 AssemblyResolve
事件)。分类 | 作用 | 核心成员/语法 | 限制/参数 | 典型场景 |
---|---|---|---|---|
自定义特性 | 为程序实体(类、方法等)添加自定义元数据 | - 继承 Attribute - 命名后缀 Attribute (可省略)- 语法: [特性名(参数)] |
- 用 [AttributeUsage] 限制目标:AttributeTargets.Class/Method/Field - AllowMultiple=true 允许多实例- Inherited=true 继承性 |
标记业务逻辑(如 [Serializable] 自定义序列化)、Unity 组件标记([RequireComponent] ) |
过时特性 | 标记成员过时,提示替换方案 | [Obsolete("提示信息", isError)] |
- isError=true 编译报错- false 仅警告 |
废弃旧接口,强制迁移新方法(如 [Obsolete("Use NewMethod()", true)] ) |
调用者信息 | 自动获取调用方的文件路径、行号、成员名 | - [CallerFilePath] - [CallerLineNumber] - [CallerMemberName] |
必须为参数设置默认值(如 string file = "" ) |
日志记录、错误追踪(捕获调用位置) |
条件编译 | 配合 #define 控制代码编译(调试/发布区分) |
[Conditional("符号名")] (需 using System.Diagnostics ) |
仅当符号定义时执行标记的方法 | 调试代码隔离(如 [Conditional("DEBUG")] ) |
DLL 导入 | 调用非托管 DLL 函数(如 C++ 库) | [DllImport("DLL名")] (需 using System.Runtime.InteropServices ) |
- 需匹配函数签名 - extern 修饰符 |
调用系统 API(如 [DllImport("user32.dll")] 调用 Windows 函数) |
反射获取 | 运行时读取特性元数据 | - Type.IsDefined(typeof(特性)) - Type.GetCustomAttributes() |
- 区分实例/静态成员 - 注意 BindingFlags.NonPublic 访问私有特性 |
框架开发(如依赖注入、AOP 拦截) |
分类 | 传统实现(接口) | 语法糖(yield return ) |
---|---|---|
核心接口 | IEnumerable (提供枚举器)IEnumerator (遍历逻辑) |
IEnumerable (仅需实现 GetEnumerator ) |
命名空间 | using System.Collections; |
using System.Collections; |
实现复杂度 | 需手动实现 MoveNext() 、Current 、Reset() |
编译器自动生成迭代器逻辑(隐式实现) |
核心方法 | - IEnumerator GetEnumerator() - bool MoveNext() - object Current - void Reset() |
- IEnumerator GetEnumerator() 中使用 yield return - 自动生成 MoveNext 和 Current |
适用场景 | 复杂遍历逻辑(如双向迭代、条件过滤) | 简单顺序遍历(如数组、列表) |
代码量 | 多行代码,显式管理光标位置(position ) |
单行 yield return ,自动维护状态 |
泛型支持 | 非泛型(object Current )需手动转型 |
支持泛型(配合 IEnumerable ) |
foreach 本质 | 1. 调用 GetEnumerator() 2. 循环 MoveNext() 3. 取 Current |
同上(编译器生成等价逻辑) |
优缺点 | - 灵活控制迭代状态 - 代码冗余,易出错 |
- 简洁易维护 - 无法直接控制底层迭代逻辑 |
特性 | 传统迭代器 | yield return 迭代器 |
---|---|---|
状态保存 | 手动维护(如 position 变量) |
编译器自动保存(局部变量闭包) |
遍历控制 | 支持中途退出、重置、逆向遍历 | 仅支持顺序遍历(yield 不可回退) |
内存占用 | 即时加载所有元素 | 延迟加载(逐个 yield ,适合大数据集) |
异常处理 | 需手动处理 Current 越界 |
自动抛出 InvalidOperationException |
线程安全 | 需手动实现同步机制 | 无内置线程安全(与普通遍历一致) |
分类 | 说明 | 核心语法/规则 | 注意事项 |
---|---|---|---|
var 隐式类型 |
自动推断局部变量类型 | var 变量 = 初始值; |
- 仅用于局部变量,需初始化 - 类型固定,不可二次赋值 |
对象初始化 | 声明时直接初始化公共成员/属性 | new 类型 { 成员1=值, 成员2=值 }; |
- 调用无参构造(可省略) - 支持混合构造函数+初始化器(后者覆盖前者) |
集合初始化 | 声明时填充元素 | new 集合类型 { 元素1, 元素2 }; |
- 支持数组、List 、Dictionary 等- 需实现 Add 方法(如 Dictionary 用 {键, 值} ) |
匿名类型 | 临时创建轻量级数据结构 | var 变量 = new { 成员1=值, 成员2=值 }; |
- 只读成员 - 无方法,仅存储数据 |
可空类型 | 值类型支持 null (Nullable ) |
类型? 变量 = null; (如 int? a = null; ) |
- 引用类型无需加 ? - 用 HasValue 判断空,Value 获值(需判空) |
空合并操作符 | 空值处理简化(?? ) |
左边值 ?? 右边值 (左边为 null 时返回右边,否则左边) |
- 支持可空类型和引用类型 - 短路求值(右边仅在左边为 null 时执行) |
内插字符串 | 字符串拼接简化($ ) |
$"文本{变量}文本", |
- 支持表达式(如 {变量.ToString()} )- 性能接近 StringBuilder |
单句简略写法 | 省略代码块大括号(仅一句) | if (条件) 语句; for(;;) 语句; |
- 仅一句代码时有效 - 避免逻辑复杂,保持可读性 |
属性简略写法 | 单行实现属性/方法(箭头语法) | 属性 { get => 值; set => 逻辑; } 方法() => 表达式; |
- 仅适用于简单逻辑 - 隐式 return (无返回值用 => 后接语句) |