Unity MyFramework:框架里的代码简化技巧(三)
前两篇写了 MyFramework 里一些常用的代码简化技巧。这一篇继续写第三组。不过这次只写真正能让调用侧代码变短的东西。也就是一眼能看到原本要写几行现在一行就能表达清楚。这类工具不是复杂系统。它们更多是项目长期开发中沉淀出来的小函数、小扩展、小短写。单独看都不大但使用频率很高。项目地址https://github.com/ZHOURUIH/MyFramework一、字符串和数字转换短写项目里数字和字符串互转非常常见。比如配置表解析UI 文本显示日志输出协议调试坐标输出百分比显示bool 状态输出原始写法通常是这样int id int.Parse(idString); float speed float.Parse(speedString); string valueText value.ToString(F2); string flag enable ? true : false;这些代码本身不难。但问题是项目里到处都要写。MyFramework 最新版本里这类转换已经大量改成扩展方法。比如字符串转整数int id idString.SToI();字符串转浮点float speed speedString.SToF();整数转字符串string idText id.IToS();long 转字符串string guidText guid.LToS();浮点转字符串并指定精度string valueText value.FToS(2);bool 转字符串string flag enable.boolToString();这类写法的价值不是 C# 原生做不到而是项目里需要统一。比如 bool 转字符串如果到处写string flag enable ? true : false;后面又有人写string flag enable ? True : False;再有人写string flag enable.ToString();项目里的输出格式就不统一。统一成string flag enable.boolToString();以后风格就固定了。真实代码里bool 转字符串是这样实现的public static string boolToString(this bool value, bool firstUpper false, bool fullUpper false) { if (fullUpper) { return value ? TRUE : FALSE; } if (firstUpper) { return value ? True : False; } return value ? true : false; }百分比显示也是一样。原本写法string percent (value * 100.0f).ToString(F1) %;现在写法string percent value.toPercent();或者指定精度string percent value.toPercent(1);真实代码public static string toPercent(this string value, int precision 1) { return (value.SToF() * 100).FToS(precision) %; } public static string toPercent(this float value, int precision 1) { return (value * 100).FToS(precision) %; }向量转字符串也统一成扩展方法。原本写法string posText pos.x.ToString(F2) , pos.y.ToString(F2) , pos.z.ToString(F2);现在写法string posText pos.V3ToS(2);真实代码public static string V3ToS(this Vector3 value, int precision 4) { return strcat(value.x.FToS(precision), ,, value.y.FToS(precision), ,, value.z.FToS(precision)); }反过来字符串转向量也可以一行完成。原本写法string[] splitList str.Split(,); Vector3 pos new(float.Parse(splitList[0]), float.Parse(splitList[1]), float.Parse(splitList[2]));现在写法Vector3 pos str.SToV3();真实代码public static Vector3 SToV3(this string str, char separate ,) { if (str.isEmpty() || str 0,0,0) { return Vector3.zero; } string[] splitList str.split(separate); if (splitList.count() 3) { return Vector3.zero; } return new(splitList[0].SToF(), splitList[1].SToF(), splitList[2].SToF()); }这类短函数的意义很明确把常见转换写成统一入口。它不会让逻辑变复杂。只是让代码更短、更统一。二、List 操作短写ListT是项目里最常用的容器之一。很多 List 操作原本都要写好几行。比如条件添加。原本写法if (condition) { list.Add(value); }现在写法list.addIf(value, condition);真实代码public static bool addIfT(this ListT list, T value, bool condition) { if (condition) { list.Add(value); } return condition; }非空才添加。原本写法if (value ! null) { list.Add(value); }现在写法list.addNotNull(value);真实代码public static bool addNotNullT(this ListT list, T value) where T : class { if (value ! null) { list.Add(value); return true; } return false; }字符串非空才添加。原本写法if (!text.isEmpty()) { list.Add(text); }现在写法list.addNotEmpty(text);真实代码public static bool addNotEmpty(this Liststring list, string value) { if (!value.isEmpty()) { list.Add(value); return true; } return false; }不重复添加。原本写法if (!list.Contains(value)) { list.Add(value); }现在写法list.addUnique(value);真实代码public static bool addUniqueT(this ListT list, T value) { if (!list.Contains(value)) { list.Add(value); return true; } return false; }有条件地不重复添加。原本写法if (condition !list.Contains(value)) { list.Add(value); }现在写法list.addUniqueIf(value, condition);真实代码public static bool addUniqueIfT(this ListT list, T value, bool condition) { if (!condition) { return false; } if (!list.Contains(value)) { list.Add(value); return true; } return false; }根据状态添加或移除。原本写法if (enable) { if (!list.Contains(value)) { list.Add(value); } } else { list.Remove(value); }现在写法list.addUniqueOrRemove(value, enable);真实代码public static void addUniqueOrRemoveT(this ListT list, T value, bool addOrRemove) { if (addOrRemove) { list.addUnique(value); } else { list.Remove(value); } }移除并返回被移除的元素。原本写法T value list[index]; list.RemoveAt(index); return value;现在写法return list.removeAt(index);真实代码public static T removeAtT(this ListT list, int index) { T value list[index]; list.RemoveAt(index); return value; }不关心顺序时可以交换到末尾再删除。现在写法return list.swapToEndAndRemove(index);真实代码public static T swapToEndAndRemoveT(this ListT list, int index) { list.swap(index, list.Count - 1); return list.removeAt(list.Count - 1); }创建新对象并添加到列表。原本写法Item item new(); list.Add(item); item.init();现在写法list.addNewItem().init();真实代码public static T addNewT(this ListT list) where T : new() { return list.add(new()); }如果添加的是对象池对象也可以写list.addClassItem().init();真实代码public static T addClassT(this ListT list) where T : ClassObject, new() { return list.add(CLASST()); }取最后一个元素。原本写法T value list null || list.Count 0 ? default : list[list.Count - 1];现在写法T value list.getLast();这类扩展函数都不复杂。但它们解决的是同一种问题不要让业务代码里到处充满重复的 if、Contains、Add、RemoveAt。比如list.addUnique(value);这一行表达得很清楚把 value 添加进列表但不要重复。这比每个地方都手写Contains Add更稳定也更统一。三、Dictionary 操作短写Dictionary的重复代码也很多。最常见的是安全取值。原本写法if (!dic.TryGetValue(key, out Value value)) { value defaultValue; }现在写法Value value dic.get(key, defaultValue);真实代码public static Value getKey, Value(this DictionaryKey, Value map, Key key, Value defaultValue) { return map ! null map.TryGetValue(key, out Value value) ? value : defaultValue; }不需要默认值时Value value dic.get(key);真实代码public static Value getKey, Value(this DictionaryKey, Value map, Key key) { if (map null) { return default; } map.TryGetValue(key, out Value value); return value; }添加或覆盖。原本写法dic[key] value;现在写法dic.addOrSet(key, value);真实代码public static void addOrSetTKey, TValue(this DictionaryTKey, TValue dic, TKey key, TValue value) { dic[key] value; }这个看起来只是换了名字但它表达更明确这个操作允许新增也允许覆盖。数值累加是更明显的简化。原本写法if (dic.TryGetValue(key, out int curValue)) { dic[key] curValue increase; } else { dic.Add(key, increase); }现在写法dic.addOrIncreaseValue(key, increase);真实代码public static void addOrIncreaseValueTKey(this DictionaryTKey, int dic, TKey key, int increase) { if (dic.TryGetValue(key, out int curValue)) { dic[key] curValue increase; } else { dic.Add(key, increase); } }根据状态添加或移除。原本写法if (isAdd) { dic.Add(key, value); } else { dic.Remove(key); }现在写法dic.addOrRemove(key, value, isAdd);真实代码public static void addOrRemoveKey, Value(this DictionaryKey, Value map, Key key, Value value, bool isAdd) { if (isAdd) { map.Add(key, value); } else { map.Remove(key); } }获取或创建普通对象。原本写法if (!map.TryGetValue(key, out Value value)) { value new(); map.Add(key, value); }现在写法map.getOrAddNew(key, out Value value);或者Value value map.getOrAddNew(key);真实代码public static bool getOrAddNewKey, Value(this DictionaryKey, Value map, Key key, out Value value) where Value : new() { if (!map.TryGetValue(key, out value)) { value new(); map.Add(key, value); return false; } return true; } public static Value getOrAddNewKey, Value(this DictionaryKey, Value map, Key key) where Value : new() { if (!map.TryGetValue(key, out Value value)) { value new(); map.Add(key, value); } return value; }获取或创建对象池对象。原本写法if (!map.TryGetValue(key, out T value)) { CLASS(out value); map.Add(key, value); }现在写法T value map.getOrAddClass(key);真实代码public static T getOrAddClassKey, T(this DictionaryKey, T map, Key key) where T : ClassObject, new() { if (!map.TryGetValue(key, out T value)) { map.Add(key, CLASS(out value)); } return value; }这类写法在事件系统、点击系统、资源系统里都很常见。比如事件监听列表mGlobalListenerEventList.getOrAddClass(info.mEventTypeID).add(info);这行代码背后做了三件事根据事件类型查找监听列表如果没有就从对象池创建一个然后把监听信息加进去如果不封装代码会变成一大段TryGetValue CLASS Add。现在一行就能表达清楚。Dictionary 这类短写非常适合框架代码。因为框架里经常会按 ID、类型、路径、状态分组。这些分组逻辑如果每次都手写字典创建代码会非常啰嗦。四、字符串截取和处理短写字符串截取也是项目里很常见的重复代码。尤其是路径、文件名、配置字段、资源名、日志文本。比如截取某个字符之前的内容。原本写法int index str.IndexOf(/); if (index 0) { str str[0..index]; }现在写法str str.rangeToFirst(/);真实代码public static string rangeToFirst(this string str, char key) { if (str null) { return str; } int endIndex str.IndexOf(key); if (endIndex 0) { return str[0..endIndex]; } return str; }截取某个字符之后的内容。现在写法str str.rangeFromFirst(/);真实代码public static string rangeFromFirst(this string str, char key) { if (str null) { return str; } int startIndex str.IndexOf(key); if (startIndex 0) { return str; } return str[(startIndex 1)..]; }截取两个字符之间的内容。原本写法int startIndex str.IndexOf((); int endIndex str.IndexOf()); if (startIndex 0 endIndex 0 endIndex startIndex) { str str[(startIndex 1)..endIndex]; }现在写法str str.rangeBetweenKeyToKey((, ));真实代码public static string rangeBetweenKeyToKey(this string str, char key0, char key1) { if (str null) { return str; } int startIndex str.IndexOf(key0); int endIndex str.IndexOf(key1); if (startIndex 0 || endIndex 0 || endIndex startIndex) { return str; } return str[(startIndex 1)..endIndex]; }移除前缀。原本写法if (str ! null str.StartsWith(prefix)) { str str[prefix.Length..]; }现在写法str str.removeStartString(prefix);真实代码public static string removeStartString(this string str, string pattern, bool caseSensitive true) { if (str null || pattern null || str.Length pattern.Length) { return str; } bool needRemove; if (caseSensitive) { needRemove str.StartsWith(pattern); } else { needRemove str.ToLower().StartsWith(pattern.ToLower()); } if (needRemove) { return str[pattern.Length..]; } return str; }移除后缀。原本写法if (str ! null str.EndsWith(suffix)) { str str[0..(str.Length - suffix.Length)]; }现在写法str str.removeEndString(suffix);真实代码public static string removeEndString(this string str, string pattern, bool caseSensitive true) { if (str null || pattern null || str.Length pattern.Length) { return str; } bool needRemove; if (caseSensitive) { needRemove str.EndsWith(pattern); } else { needRemove str.ToLower().EndsWith(pattern.ToLower()); } if (needRemove) { return str[0..(str.Length - pattern.Length)]; } return str; }确保前缀存在。原本写法if (!path.StartsWith(Assets/)) { path Assets/ path; }现在写法path path.ensurePrefix(Assets/);真实代码public static string ensurePrefix(this string str, string prefix) { if (!str.StartsWith(prefix)) { return prefix str; } return str; }确保后缀存在。原本写法if (!path.EndsWith(/)) { path /; }现在写法path path.ensureSuffix(/);真实代码public static string ensureSuffix(this string str, string prefix) { if (!str.EndsWith(prefix)) { return str prefix; } return str; }这类短写非常适合路径处理。因为路径处理里经常要做这些事去掉前缀去掉后缀截取文件夹截取文件名保证路径以/结尾保证路径以Assets/开头截取某个标记之间的内容如果每个地方都写IndexOf、Substring、StartsWith、EndsWith代码会非常散。封装成字符串扩展以后调用侧就更像自然语言。比如path path.ensureSuffix(/);这行代码一眼就能看懂确保 path 有/后缀。这就是代码简化的意义。五、数组、Span、byte[] 操作短写数组访问经常要做边界判断。原本写法T value default; if (array ! null index 0 index array.Length) { value array[index]; }现在写法T value array.get(index);真实代码public static T getT(this T[] list, int index) { if (list.isEmpty() || index 0 || index list.Length) { return default; } return list[index]; }数组设置也是一样。原本写法if (array ! null index 0 index array.Length) { array[index] value; }现在写法array.set(index, value);真实代码public static void setT(this T[] list, int index, T value) { if (list.isEmpty() || index 0 || index list.Length) { return; } list[index] value; }取第一个元素。原本写法T value array null || array.Length 0 ? default : array[0];现在写法T value array.first();真实代码public static T firstT(this T[] list) { if (list.isEmpty()) { return default; } return list[0]; }数组安全遍历。原本写法if (array ! null) { foreach (var item in array) { ... } }现在写法foreach (var item in array.safe()) { ... }真实代码public static T[] safeT(this T[] original) { return original ?? EmptyArrayT.getEmptyList(); }判断数组里是否包含某个值。原本写法bool contains false; if (array ! null) { for (int i 0; i array.Length; i) { if (equal(array[i], value)) { contains true; break; } } }现在写法bool contains array.contains(value);真实代码public static bool containsT(this T[] list, T value) { if (list.isEmpty()) { return false; } int length list.Length; for (int i 0; i length; i) { if (equal(list[i], value)) { return true; } } return false; }byte[] 转字符串也可以短写。原本写法string text Encoding.UTF8.GetString(bytes);现在写法string text bytes.bytesToString();真实代码public static string bytesToString(this byte[] bytes, Encoding encoding null) { if (bytes.isEmpty()) { return string.Empty; } // 默认为UTF8 return removeLastZero((encoding ?? Encoding.UTF8).GetString(bytes)); }Spanbyte 也可以保持同样写法string text span.bytesToString();真实代码public static string bytesToString(this Spanbyte bytes, Encoding encoding null) { if (bytes null) { return null; } if (bytes.Length 0) { return string.Empty; } // 默认为UTF8 return removeLastZero((encoding ?? Encoding.UTF8).GetString(bytes)); }这类短写解决的是两个问题。第一减少边界判断。第二统一常用转换。数组访问如果每次都手写边界判断代码会很长。但如果不判断又容易越界。所以框架提供get()、set()、first()这种短写以后调用侧更简单。byte[] 转字符串也是同理。项目里经常会有网络数据、文件数据、配置数据需要转字符串。如果到处直接写Encoding.UTF8.GetString(bytes)还要考虑空数组、尾部 0、编码默认值等问题。统一写成bytes.bytesToString();调用侧就更干净。总结这一篇基于 MyFramework 最新版本重新调整了 5 类真正能让调用侧变短的技巧字符串和数字转换短写List 操作短写Dictionary 操作短写字符串截取和处理短写数组、Span、byte[] 操作短写这一版里要特别注意很多转换函数已经是扩展方法写法。比如idString.SToI(); speedString.SToF(); id.IToS(); guid.LToS(); value.FToS(2); enable.boolToString(); pos.V3ToS(2); 0.5.toPercent(); 0.5f.toPercent();它们的共同点是原本要写几行的固定模式现在可以压成一行。比如if (!list.Contains(value)) { list.Add(value); }变成list.addUnique(value);比如if (dic.TryGetValue(key, out int curValue)) { dic[key] curValue increase; } else { dic.Add(key, increase); }变成dic.addOrIncreaseValue(key, increase);比如int index str.IndexOf(/); if (index 0) { str str[0..index]; }变成str str.rangeToFirst(/);比如if (array ! null index 0 index array.Length) { value array[index]; }变成value array.get(index);这些不是为了隐藏业务逻辑。它们隐藏的是每天都会重复出现的样板代码。一句话总结代码简化不是少写业务。而是不要让业务代码被重复的固定写法淹没。

相关新闻

终极指南:用DistroAV实现专业NDI网络音视频传输的完整方案

终极指南:用DistroAV实现专业NDI网络音视频传输的完整方案

终极指南:用DistroAV实现专业NDI网络音视频传输的完整方案 【免费下载链接】obs-ndi DistroAV (formerly OBS-NDI): NDI integration for OBS Studio 项目地址: https://gitcode.com/gh_mirrors/ob/obs-ndi DistroAV(原名OBS-NDI)是一…

2026/7/6 13:03:49 阅读更多 →
AD 23 与 AutoCAD 2024 协同:DXF 板框导入的 5 项预处理与 1 个精度保障技巧

AD 23 与 AutoCAD 2024 协同:DXF 板框导入的 5 项预处理与 1 个精度保障技巧

AD 23与AutoCAD 2024高效协同:DXF板框导入的预处理全流程与精度控制实战在硬件开发领域,PCB工程师与结构工程师的协同效率直接影响产品开发周期。当结构工程师使用AutoCAD 2024完成机箱设计后,如何确保其提供的DXF文件能够精准导入Altium Des…

2026/7/6 12:57:42 阅读更多 →
测试转大模型:AI 测试工程师的能力跃迁,把学习路线落到项目证据

测试转大模型:AI 测试工程师的能力跃迁,把学习路线落到项目证据

《测试转大模型:AI 测试工程师的能力跃迁,把学习路线落到项目证据》看起来是个大话题,但真落到项目里,常常就是几个具体选择。下面我尽量按实际开发时会遇到的问题来讲。摘要这篇面向想进入 AI 测试和质量工程方向的软件测试工程师…

2026/7/6 12:55:41 阅读更多 →

最新新闻

AI 知识库系统落地实战指南

AI 知识库系统落地实战指南

在企业日常运营中,最让人头疼的往往不是数据太少,而是数据太“乱”。想象一下这样的场景:新员工入职想查某个项目的历史决策记录,翻遍了共享盘里的几百个 Word 和 PDF 也没找到;客服面对用户咨询,需要在十几…

2026/7/6 13:50:44 阅读更多 →
智能座舱软件开发全解析:中间件、车云协同与高并发低延迟架构实战

智能座舱软件开发全解析:中间件、车云协同与高并发低延迟架构实战

前言 随着汽车朝智能化、网联化、电动化迈进,车内的“座舱”不再只是播放音乐和放手机的地方。它已经变成一个复合型的体验中枢——把语音助手、高清屏幕、全景影像、多屏联动、实时流媒体和车云服务等不同能力,整合成乘客能直接感知的体验。你在夜间行驶时对着方向盘喊一句导…

2026/7/6 13:50:44 阅读更多 →
文字直达可视化:paperxie AI 科研绘图重构学术配图全链路体验

文字直达可视化:paperxie AI 科研绘图重构学术配图全链路体验

paperxie-免费查重复率aigc检测/开题报告/毕业论文/智能排版/文献综述/科研绘图科研绘图 - PaperXie智能写作PaperXie免费论文查重检测-首款免费论文检测软件,为毕业生提供专业的论文重复率检测、论文降重、Aigc检测、智能排版 、论文写作等一站式服务。https://www.paperxie.c…

2026/7/6 13:48:43 阅读更多 →
Vue.js 3 的设计思路

Vue.js 3 的设计思路

1. 声明式地描述UI Vue.js 3是一个声明式UI框架,编写前端页面涉及到以下内容: 1. DOM元素:例如是div还是a标签。2. 属性:乳a标签的href属性,或id,class等通用属性。3. 事件:如click&#xff0c…

2026/7/6 13:48:43 阅读更多 →
文字一键转学术可视化:paperxie 重构科研绘图全链路,消解学术作图多重内耗

文字一键转学术可视化:paperxie 重构科研绘图全链路,消解学术作图多重内耗

paperxie-免费查重复率aigc检测/开题报告/毕业论文/智能排版/文献综述/科研绘图科研绘图 - PaperXie智能写作PaperXie免费论文查重检测-首款免费论文检测软件,为毕业生提供专业的论文重复率检测、论文降重、Aigc检测、智能排版 、论文写作等一站式服务。https://www.paperxie.c…

2026/7/6 13:48:43 阅读更多 →
管理 Linux 联网

管理 Linux 联网

1.RHEL10 版本特点在 RHEL7 版本中,同时支持 network.service 和 NetworkManager.service(简称 NM)。在 RHEL8 上默认只能通过 NM 进行网络配置,包括动态 ip 和静态 ip,若不开启 NM,否则无法使用网络 RHEL8…

2026/7/6 13:46:41 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻