C# 语言入门(六)运算符重载、接口、预处理、异常、特性
本篇核心知识点运算符重载、接口 interface、抽象类与接口核心区别、命名空间 namespace、预处理指令 (#define/#if/#endif 等)、正则表达式 Regex、异常处理 try-catch-finally-throw、自定义异常、装箱拆箱、特性 Attribute 基础一、运算符重载1. 概念自定义类 / 结构体原本无法直接使用 - * / !等运算符通过operator关键字重载运算符自定义运算逻辑简化代码替代冗余Add/Sub成员方法。2. 核心规则语法public static 返回类型 operator 运算符(参数列表)二元运算符需两个参数只能重载 C# 允许的运算符禁止重载. ?: :: sizeof相等与不等!必须成对重载否则编译警告浮点数值判等不能直接用需判断差值极小阈值不改变运算符优先级、结合性、操作数数量。3. 代码示例二维向量 Pointclass 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 大量使用。二、接口 interface1. 概念接口是一套行为规范契约仅声明方法 / 属性无实现类 / 结构体实现接口必须完整实现所有接口成员用于多行为统一约束。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/CocosUI 点击、拖拽、碰撞统一使用接口引擎回调全部基于接口只关心对象是否具备对应行为不关心具体类型。三、命名空间 namespace1. 概念相当于代码文件夹隔离同名类解决多文件、多库类名冲突问题。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 / #endif1. 概念编译前执行的标记指令不生成变量仅定义符号用于跨平台、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标记自动消失。五、正则表达式 Regex1. 概念用于文本匹配、提取、校验字符串的规则模板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-throw1. 核心概念程序运行错误称为异常若不捕获会直接程序崩溃通过try监控危险代码catch捕获处理finally无论是否异常必执行throw主动抛出异常。2 关键字分工try包裹可能报错的代码块catch(异常类型 ex)捕获对应异常可获取异常信息ex.Messagefinally无论正常 / 异常代码一定会执行释放资源专用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)]标记弃用 APItrue 编译报错false 仅警告[Conditional(DEBUG)]条件编译仅定义标记时方法生效。3. 自定义特性继承Attribute实现自定义标记存储开发备注、Bug 记录等元数据通过反射读取。代码示例弃用特性[Obsolete(该方法已废弃请使用CalcNew(), false)] static void OldCalc(){ Console.WriteLine(旧计算逻辑); }九、反射前置1. 概念通过字符串类型名动态获取类、方法、属性信息运行时创建对象、调用函数依赖特性读取元数据。核心 APItypeof(类)获取类型Type对象Type.GetMethods()获取所有方法Type.GetCustomAttributes()读取附加特性。拓展游戏热更新、配置表解析、框架插件系统底层全部基于反射。十、拓展1 接口与抽象类核心区分多接口实现作用2 预处理指令作用Debug/Release 区分原理3 异常三层结构 try-catch-finally 使用场景自定义异常优势4 运算符重载成对规则、浮点判等坑5 特性本质元数据反射读取流程6 装箱拆箱性能缺陷优化方案。