本篇核心知识点:运算符重载、接口 interface、抽象类与接口核心区别、命名空间 namespace、预处理指令 (#define/#if/#endif 等)、正则表达式 Regex、异常处理 try-catch-finally-throw、自定义异常、装箱拆箱、特性 Attribute 基础
一、运算符重载
1. 概念
自定义类 / 结构体原本无法直接使用+ - * / == !=等运算符,通过operator关键字重载运算符,自定义运算逻辑,简化代码,替代冗余Add/Sub成员方法。
2. 核心规则
语法:
public static 返回类型 operator 运算符(参数列表),二元运算符需两个参数;只能重载 C# 允许的运算符,禁止重载
. ?: :: sizeof;相等
==与不等!=必须成对重载,否则编译警告;浮点数值判等不能直接用
==,需判断差值极小阈值;不改变运算符优先级、结合性、操作数数量。
3. 代码示例:二维向量 Point
class Point{ public float X, Y; public Point(float x = 0, float y = 0){ X = x; Y = y; } // 重载 + 向量相加 public static Point operator +(Point p1, Point p2) { return new Point(p1.X + p2.X, p1.Y + p2.Y); } // 重载 - 向量相减 public static Point operator -(Point p1, Point p2){ return new Point(p1.X - p2.X, p1.Y - p2.Y); } // 重载 == 相等判断(浮点容错) public static bool operator ==(Point p1, Point p2){ float eps = 1e-6f; return Math.Abs(p1.X - p2.X) < eps && Math.Abs(p1.Y - p2.Y) < eps; } // 成对重载 != public static bool operator !=(Point p1, Point p2){ return !(p1 == p2); } public void Print(){ Console.WriteLine($"X:{X}, Y:{Y}"); } } // 测试 static void Main(){ Point a = new Point(2, 3); Point b = new Point(1, 1); Point c = a + b; c.Print(); Console.WriteLine(a != b); }4. 拓展
1 向量
数字、向量
向量均可分别重载;
2 class 默认==比较堆内存地址,重载后实现值对比;
3 TS 无运算符重载,C++/C# 支持,游戏 Vector2/3 大量使用。
二、接口 interface
1. 概念
接口是一套行为规范契约,仅声明方法 / 属性,无实现;类 / 结构体实现接口,必须完整实现所有接口成员,用于多行为统一约束。
2. 核心特性
接口所有成员默认且只能是 public,不能写访问修饰符;
只能包含声明(方法、属性、事件),无字段、无构造函数;
不能实例化,仅能被子类实现;
C# 类单继承(仅一个父类),但可同时实现多个接口,弥补多继承缺失;
接口之间可多继承;
抽象类可写实现代码,接口全部为抽象无实现。
3. 抽象类 vs 接口(核心对比)
| 对比维度 | abstract 抽象类 | interface 接口 |
|---|---|---|
| 成员实现 | 可包含已实现普通方法、抽象方法 | 全部只有声明,无任何实现 |
| 构造函数 | 可写构造函数 | 无构造函数 |
| 继承规则 | 类只能继承一个抽象父类 | 一个类可实现 N 个接口 |
| 成员权限 | public/protected/private 均可 | 强制全部 public |
| 字段 | 可定义成员变量 | 不允许定义字段 |
| 使用场景 | 同类事物公共逻辑复用 | 不同事物统一行为标准(如点击、受伤) |
4. 代码示例
// 定义两个行为接口 interface IHit{ void TakeDamage(int atk); // 受伤害 } interface IAnim{ void PlayIdle(); // 播放待机动画 } // 植物类同时实现两个接口 class SunFlower : IHit, IAnim{ private int hp = 100; // 实现接口受伤害方法 public void TakeDamage(int atk){ hp -= atk; Console.WriteLine("向日葵受伤"); } // 实现动画接口 public void PlayIdle(){ Console.WriteLine("播放向日葵待机动画"); } static void Main(){ IHit plant = new SunFlower(); plant.Take(10); // 仅能调用接口定义方法 }5. 实战拓展(Unity/Cocos)
UI 点击、拖拽、碰撞统一使用接口;引擎回调全部基于接口,只关心对象是否具备对应行为,不关心具体类型。
三、命名空间 namespace
1. 概念
相当于代码文件夹,隔离同名类,解决多文件、多库类名冲突问题。
2. 特性
语法:
namespace 名称 { 所有类/结构体 };访问方式:
命名空间.类名;using 命名空间;简写,无需完整路径;支持多层嵌套(文件夹嵌套);
不同命名空间下同名类属于完全不同类型。
3. 代码示例
namespace Lesson7{ class Point { public int X; } } namespace Lesson8{ class Point { public float X; } } static void Main(){ // 完整路径区分同名类 Lesson7.Point p1 = new Lesson7(); Lesson8.Point p2 = new Lesson8(); }拓展
Unity 大量命名空间区分引擎模块,冲突时必须写完整命名空间限定。
四、预处理指令 #define / #if / #endif
1. 概念
编译前执行的标记指令,不生成变量,仅定义符号,用于跨平台、Debug/Release 代码区分。
2. 核心指令
#define 符号名:定义编译标记,必须放在文件最顶部;#if / #elif / #else / #endif:判断标记是否存在,不存在代码直接不参与编译;#undef:取消已定义标记;#warning / #error:编译时抛出警告 / 错误;#region / #endregion:代码折叠块。
3. 特性
C# 预处理无 C++ 宏替换功能,仅做条件编译判断;
系统自带内置标记
DEBUG(调试模式自动定义);未定义符号区间代码灰色,编译直接忽略,不报错。
4 跨平台实战代码
#define IOS // 定义IOS平台标记 static void GameInit() { #if IOS Console.WriteLine("IOS平台初始化"); #elif ANDROID Console.WriteLine("安卓平台初始化"); #else Console.WriteLine("Windows通用逻辑"); #endif }拓展
游戏跨平台生命周期、SDK 适配全部使用预处理区分;Release 模式DEBUG标记自动消失。
五、正则表达式 Regex
1. 概念
用于文本匹配、提取、校验字符串的规则模板,C# 内置System.Text.RegularExpressions.Regex类实现。
2. 常用元字符
\d数字 0-9;\D非数字
\w字母数字下划线;\b单词边界
+至少 1 次;*0 或多次;?0 或 1 次
{n}精准匹配 n 次;[]字符集
3. 基础代码示例(提取数字)
using System.Text.RegularExpressions; static void TestRegex() { string str = "编号995 分数05"; // 匹配连续两位数字 Regex reg = new Regex(@"\d{2}"); MatchCollection mc = reg.Matches(str); foreach(Match m in mc) { Console.WriteLine(m.Value); } }实战场景
账号校验、配置文本解析、日志关键字提取。
六、异常处理 try-catch-finally-throw
1. 核心概念
程序运行错误称为异常,若不捕获会直接程序崩溃;通过try监控危险代码,catch捕获处理,finally无论是否异常必执行,throw主动抛出异常。
2 关键字分工
try:包裹可能报错的代码块;catch(异常类型 ex):捕获对应异常,可获取异常信息ex.Message;finally:无论正常 / 异常,代码一定会执行(释放资源专用);throw new Exception("提示"):手动抛出异常,向上层传递。
3. 基础示例(除数为零异常)
static float Div(float a, float b) { if (b == 0){ // 主动抛出异常 throw new Exception("除数不能为0"); } return a / b; } static void Calc(){ float res = 0; try { res = Div(10, 0); } catch(Exception ex){ Console.WriteLine("捕获异常:" + ex.Message); res = -1; // 异常默认值 } finally{ Console.WriteLine("计算结束,释放临时资源"); } Console.WriteLine("结果:" + res); }4. 自定义异常
概念
继承Exception自定义异常类,区分不同错误类型,精准分类捕获处理。
// 数组下限越界异常 class IndexLowException : Exception{ public IndexLowException(string msg) : base(msg) { } } // 数组上限越界异常 class IndexHighException : Exception{ public IndexHighException(string msg) : base(msg) { } } static void SetArr(int[] arr, int idx, int val){ if(idx < 0) throw new IndexLowException("下标小于0"); if(idx >= arr.Length) throw new IndexHighException("下标超出数组长度"); arr[idx] = val; } // 分层捕获 static void TestArr(){ int[] data = new int[5]; try{ SetArr(data, 8, 99); } catch(IndexLowException ex){ Console.WriteLine("下限错误:"+ex.Message); } catch(IndexHighException ex){ Console.WriteLine("上限错误:"+ex.Message); } }拓展
1 无法处理的异常可再次throw向上抛给上层调用者;
2 文件、网络、数据库资源释放写在finally,保证资源关闭。
七、装箱 & 拆箱
1. 装箱(隐式)
值类型 → object 引用类型,栈数据拷贝到堆,自动完成。
int num = 10; object obj = num; // 装箱2. 拆箱(显式强制转换)
堆 object 转回栈值类型,必须强制转换,类型不匹配抛异常。
int res = (int)obj; // 拆箱特性
频繁装箱拆箱产生大量堆临时对象,GC 压力大,高性能游戏尽量避免。
八、特性 Attribute(基础)
1. 概念
附加在类 / 方法 / 属性上的元数据标记,不影响程序运行,用于编译器提示、反射读取配置信息。
2. 系统内置常用特性
[Obsolete("提示文本", true)]标记弃用 API,true 编译报错,false 仅警告;[Conditional("DEBUG")]条件编译,仅定义标记时方法生效。
3. 自定义特性
继承Attribute实现自定义标记,存储开发备注、Bug 记录等元数据,通过反射读取。
代码示例(弃用特性)
[Obsolete("该方法已废弃,请使用CalcNew()", false)] static void OldCalc(){ Console.WriteLine("旧计算逻辑"); }九、反射前置
1. 概念
通过字符串类型名动态获取类、方法、属性信息,运行时创建对象、调用函数,依赖特性读取元数据。
核心 API
typeof(类)获取类型Type对象;Type.GetMethods()获取所有方法;Type.GetCustomAttributes()读取附加特性。
拓展
游戏热更新、配置表解析、框架插件系统底层全部基于反射。
十、拓展
1 接口与抽象类核心区分,多接口实现作用;
2 预处理指令作用,Debug/Release 区分原理;
3 异常三层结构 try-catch-finally 使用场景,自定义异常优势;
4 运算符重载成对规则、浮点判等坑;
5 特性本质元数据,反射读取流程;
6 装箱拆箱性能缺陷优化方案。