From 5318f5a38f6d2547b9085c3413979b4163bb6c20 Mon Sep 17 00:00:00 2001
From: GeWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Sat, 31 Jan 2026 14:45:16 +0800
Subject: [PATCH] =?UTF-8?q?refactor(functional):=20=E9=87=8D=E6=9E=84?=
=?UTF-8?q?=E5=87=BD=E6=95=B0=E5=BC=8F=E7=BC=96=E7=A8=8B=E6=89=A9=E5=B1=95?=
=?UTF-8?q?=E6=96=B9=E6=B3=95=E7=BB=84=E7=BB=87=E7=BB=93=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 将原有的 PipeExtensions.cs 文件拆分为多个专门的功能模块
- 新增 ControlExtensions.cs 专门处理控制流扩展方法
- 新增 EnumerableExtensions.cs 专门处理集合相关扩展方法
- 新增 FunctionExtensions.cs 专门处理函数式编程核心功能
- 新增 TypeExtensions.cs 专门处理类型转换相关扩展方法
- 移除 PipeExtensions.cs 中的集合操作、函数式核心功能和控制流方法
- 保留 PipeExtensions.cs 中的管道操作相关核心方法
- 优化代码组织结构提升可维护性和可读性
---
.../collections/EnumerableExtensions.cs | 59 ++++
.../functional/control/ControlExtensions.cs | 118 ++++++++
.../functions/FunctionExtensions.cs | 125 ++++++++
.../functional/pipe/PipeExtensions.cs | 266 +-----------------
.../functional/types/TypeExtensions.cs | 44 +++
5 files changed, 348 insertions(+), 264 deletions(-)
create mode 100644 GFramework.Core/functional/collections/EnumerableExtensions.cs
create mode 100644 GFramework.Core/functional/control/ControlExtensions.cs
create mode 100644 GFramework.Core/functional/functions/FunctionExtensions.cs
create mode 100644 GFramework.Core/functional/types/TypeExtensions.cs
diff --git a/GFramework.Core/functional/collections/EnumerableExtensions.cs b/GFramework.Core/functional/collections/EnumerableExtensions.cs
new file mode 100644
index 0000000..1fb2e09
--- /dev/null
+++ b/GFramework.Core/functional/collections/EnumerableExtensions.cs
@@ -0,0 +1,59 @@
+// Copyright (c) 2025 GeWuYou
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+namespace GFramework.Core.functional.collections;
+
+///
+/// 提供集合的函数式编程扩展方法
+///
+public static class EnumerableExtensions
+{
+ ///
+ /// Map:对集合中的每个元素应用函数
+ ///
+ /// 源集合元素的类型
+ /// 映射后集合元素的类型
+ /// 要映射的源集合
+ /// 用于转换元素的函数
+ /// 映射后的元素序列
+ public static IEnumerable Map(
+ this IEnumerable source,
+ Func selector)
+ => source.Select(selector);
+
+ ///
+ /// Filter:过滤集合
+ ///
+ /// 集合元素的类型
+ /// 要过滤的源集合
+ /// 用于确定是否包含元素的条件函数
+ /// 满足条件的元素序列
+ public static IEnumerable Filter(
+ this IEnumerable source,
+ Func predicate)
+ => source.Where(predicate);
+
+ ///
+ /// Reduce:将集合归约为单个值
+ ///
+ /// 集合元素的类型
+ /// 归约结果的类型
+ /// 要归约的源集合
+ /// 初始累加值
+ /// 累加器函数
+ /// 归约后的最终值
+ public static TResult Reduce(
+ this IEnumerable source,
+ TResult seed,
+ Func accumulator)
+ => source.Aggregate(seed, accumulator);
+}
diff --git a/GFramework.Core/functional/control/ControlExtensions.cs b/GFramework.Core/functional/control/ControlExtensions.cs
new file mode 100644
index 0000000..2e0ab2d
--- /dev/null
+++ b/GFramework.Core/functional/control/ControlExtensions.cs
@@ -0,0 +1,118 @@
+// Copyright (c) 2025 GeWuYou
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+namespace GFramework.Core.functional.control;
+
+///
+/// 控制流扩展方法类,提供函数式编程风格的控制结构
+///
+public static class ControlExtensions
+{
+ ///
+ /// Match:模式匹配(类似switch表达式)
+ ///
+ /// 输入值的类型
+ /// 匹配结果的类型
+ /// 要进行模式匹配的输入值
+ /// 匹配案例数组,每个包含谓词和处理器
+ /// 匹配到的处理结果
+ /// 当没有匹配的案例时抛出
+ public static TResult Match(
+ this TSource value,
+ params (Func predicate, Func handler)[] cases)
+ {
+ foreach (var (predicate, handler) in cases)
+ {
+ if (predicate(value))
+ return handler(value);
+ }
+ throw new InvalidOperationException("No matching case found");
+ }
+
+ ///
+ /// MatchOrDefault:带默认值的模式匹配
+ ///
+ /// 输入值的类型
+ /// 匹配结果的类型
+ /// 要进行模式匹配的输入值
+ /// 当没有匹配案例时的默认返回值
+ /// 匹配案例数组,每个包含谓词和处理器
+ /// 匹配到的处理结果或默认值
+ public static TResult MatchOrDefault(
+ this TSource value,
+ TResult defaultValue,
+ params (Func predicate, Func handler)[] cases)
+ {
+ foreach (var (predicate, handler) in cases)
+ {
+ if (predicate(value))
+ return handler(value);
+ }
+ return defaultValue;
+ }
+
+ ///
+ /// If:条件执行
+ ///
+ /// 输入值的类型
+ /// 要进行条件判断的输入值
+ /// 条件判断函数
+ /// 条件为真时执行的转换函数
+ /// 条件为真时返回转换后的值,否则返回原值
+ public static TSource If(
+ this TSource value,
+ Func predicate,
+ Func thenFunc)
+ => predicate(value) ? thenFunc(value) : value;
+
+ ///
+ /// IfElse:条件分支
+ ///
+ /// 输入值的类型
+ /// 要进行条件判断的输入值
+ /// 条件判断函数
+ /// 条件为真时执行的转换函数
+ /// 条件为假时执行的转换函数
+ /// 根据条件返回相应的转换结果
+ public static TSource IfElse(
+ this TSource value,
+ Func predicate,
+ Func thenFunc,
+ Func elseFunc)
+ => predicate(value) ? thenFunc(value) : elseFunc(value);
+
+ ///
+ /// TakeIf:条件返回值或null
+ ///
+ /// 输入值的类型
+ /// 要进行条件判断的输入值
+ /// 条件判断函数
+ /// 条件为真时返回原值,否则返回null
+ public static TSource? TakeIf(
+ this TSource value,
+ Func predicate)
+ where TSource : class
+ => predicate(value) ? value : null;
+
+ ///
+ /// TakeUnless:条件相反的TakeIf
+ ///
+ /// 输入值的类型
+ /// 要进行条件判断的输入值
+ /// 条件判断函数
+ /// 条件为假时返回原值,否则返回null
+ public static TSource? TakeUnless(
+ this TSource value,
+ Func predicate)
+ where TSource : class
+ => !predicate(value) ? value : null;
+}
diff --git a/GFramework.Core/functional/functions/FunctionExtensions.cs b/GFramework.Core/functional/functions/FunctionExtensions.cs
new file mode 100644
index 0000000..b2c04e1
--- /dev/null
+++ b/GFramework.Core/functional/functions/FunctionExtensions.cs
@@ -0,0 +1,125 @@
+// Copyright (c) 2025 GeWuYou
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+namespace GFramework.Core.functional.functions;
+
+///
+/// 函数式编程扩展方法集合,提供柯里化、偏函数应用、重复执行、安全执行和缓存等功能
+///
+public static class FunctionExtensions
+{
+ ///
+ /// Curry:将二参数函数转换为柯里化形式
+ ///
+ /// 第一个参数的类型
+ /// 第二个参数的类型
+ /// 函数返回结果的类型
+ /// 要柯里化的二参数函数
+ /// 柯里化后的函数,接受一个参数并返回另一个函数
+ public static Func> Curry(
+ this Func func)
+ => x => y => func(x, y);
+
+ ///
+ /// Uncurry:将柯里化函数转换回二参数函数
+ ///
+ /// 第一个参数的类型
+ /// 第二个参数的类型
+ /// 函数返回结果的类型
+ /// 要取消柯里化的函数
+ /// 恢复为二参数的函数
+ public static Func Uncurry(
+ this Func> func)
+ => (x, y) => func(x)(y);
+
+ ///
+ /// Partial:部分应用函数(固定第一个参数)
+ ///
+ /// 第一个参数的类型
+ /// 第二个参数的类型
+ /// 函数返回结果的类型
+ /// 要部分应用的二参数函数
+ /// 要固定的第一个参数值
+ /// 部分应用后的函数,只接受第二个参数
+ public static Func Partial(
+ this Func func,
+ T1 firstArg)
+ => x => func(firstArg, x);
+
+ ///
+ /// Repeat:重复执行函数n次
+ ///
+ /// 输入值的类型
+ /// 初始输入值
+ /// 重复执行的次数
+ /// 要重复执行的函数
+ /// 经过多次变换后的最终值
+ public static TSource Repeat(
+ this TSource value,
+ int times,
+ Func func)
+ {
+ var result = value;
+ // 循环执行指定次数的函数调用
+ for (int i = 0; i < times; i++)
+ {
+ result = func(result);
+ }
+ return result;
+ }
+
+ ///
+ /// Try:安全执行,捕获异常
+ ///
+ /// 输入值的类型
+ /// 函数返回结果的类型
+ /// 要传递给函数的输入值
+ /// 要安全执行的函数
+ /// 包含执行状态、结果和错误信息的元组
+ public static (bool success, TResult? result, Exception? error) Try(
+ this TSource value,
+ Func func)
+ {
+ try
+ {
+ return (true, func(value), null);
+ }
+ catch (Exception ex)
+ {
+ return (false, default, ex);
+ }
+ }
+
+ ///
+ /// Memoize:缓存函数结果
+ ///
+ /// 函数输入参数的类型
+ /// 函数返回结果的类型
+ /// 要缓存结果的函数
+ /// 带有缓存功能的包装函数
+ public static Func Memoize(
+ this Func func)
+ where TSource : notnull
+ {
+ var cache = new Dictionary();
+ return x =>
+ {
+ // 尝试从缓存中获取结果
+ if (cache.TryGetValue(x, out var result))
+ return result;
+ // 缓存未命中时计算结果并存储
+ result = func(x);
+ cache[x] = result;
+ return result;
+ };
+ }
+}
diff --git a/GFramework.Core/functional/pipe/PipeExtensions.cs b/GFramework.Core/functional/pipe/PipeExtensions.cs
index 3ce37ad..595789e 100644
--- a/GFramework.Core/functional/pipe/PipeExtensions.cs
+++ b/GFramework.Core/functional/pipe/PipeExtensions.cs
@@ -73,46 +73,6 @@ public static class PipeExtensions
return value;
}
- ///
- /// Map:对集合中的每个元素应用函数
- ///
- /// 源集合元素的类型
- /// 映射后集合元素的类型
- /// 要映射的源集合
- /// 用于转换元素的函数
- /// 映射后的元素序列
- public static IEnumerable Map(
- this IEnumerable source,
- Func selector)
- => source.Select(selector);
-
- ///
- /// Filter:过滤集合
- ///
- /// 集合元素的类型
- /// 要过滤的源集合
- /// 用于确定是否包含元素的条件函数
- /// 满足条件的元素序列
- public static IEnumerable Filter(
- this IEnumerable source,
- Func predicate)
- => source.Where(predicate);
-
- ///
- /// Reduce:将集合归约为单个值
- ///
- /// 集合元素的类型
- /// 归约结果的类型
- /// 要归约的源集合
- /// 初始累加值
- /// 累加器函数
- /// 归约后的最终值
- public static TResult Reduce(
- this IEnumerable source,
- TResult seed,
- Func accumulator)
- => source.Aggregate(seed, accumulator);
-
///
/// Apply:将函数应用于值(柯里化辅助)
///
@@ -125,140 +85,7 @@ public static class PipeExtensions
this Func func,
TSource value)
=> func(value);
-
- ///
- /// Curry:将二参数函数转换为柯里化形式
- ///
- /// 第一个参数的类型
- /// 第二个参数的类型
- /// 函数返回结果的类型
- /// 要柯里化的二参数函数
- /// 柯里化后的函数,接受一个参数并返回另一个函数
- public static Func> Curry(
- this Func func)
- => x => y => func(x, y);
-
- ///
- /// Uncurry:将柯里化函数转换回二参数函数
- ///
- /// 第一个参数的类型
- /// 第二个参数的类型
- /// 函数返回结果的类型
- /// 要取消柯里化的函数
- /// 恢复为二参数的函数
- public static Func Uncurry(
- this Func> func)
- => (x, y) => func(x)(y);
-
- ///
- /// Partial:部分应用函数(固定第一个参数)
- ///
- /// 第一个参数的类型
- /// 第二个参数的类型
- /// 函数返回结果的类型
- /// 要部分应用的二参数函数
- /// 要固定的第一个参数值
- /// 部分应用后的函数,只接受第二个参数
- public static Func Partial(
- this Func func,
- T1 firstArg)
- => x => func(firstArg, x);
-
- ///
- /// Match:模式匹配(类似switch表达式)
- ///
- /// 输入值的类型
- /// 匹配结果的类型
- /// 要进行模式匹配的输入值
- /// 匹配案例数组,每个包含谓词和处理器
- /// 匹配到的处理结果
- /// 当没有匹配的案例时抛出
- public static TResult Match(
- this TSource value,
- params (Func predicate, Func handler)[] cases)
- {
- foreach (var (predicate, handler) in cases)
- {
- if (predicate(value))
- return handler(value);
- }
- throw new InvalidOperationException("No matching case found");
- }
-
- ///
- /// MatchOrDefault:带默认值的模式匹配
- ///
- /// 输入值的类型
- /// 匹配结果的类型
- /// 要进行模式匹配的输入值
- /// 当没有匹配案例时的默认返回值
- /// 匹配案例数组,每个包含谓词和处理器
- /// 匹配到的处理结果或默认值
- public static TResult MatchOrDefault(
- this TSource value,
- TResult defaultValue,
- params (Func predicate, Func handler)[] cases)
- {
- foreach (var (predicate, handler) in cases)
- {
- if (predicate(value))
- return handler(value);
- }
- return defaultValue;
- }
-
- ///
- /// If:条件执行
- ///
- /// 输入值的类型
- /// 要进行条件判断的输入值
- /// 条件判断函数
- /// 条件为真时执行的转换函数
- /// 条件为真时返回转换后的值,否则返回原值
- public static TSource If(
- this TSource value,
- Func predicate,
- Func thenFunc)
- => predicate(value) ? thenFunc(value) : value;
-
- ///
- /// IfElse:条件分支
- ///
- /// 输入值的类型
- /// 要进行条件判断的输入值
- /// 条件判断函数
- /// 条件为真时执行的转换函数
- /// 条件为假时执行的转换函数
- /// 根据条件返回相应的转换结果
- public static TSource IfElse(
- this TSource value,
- Func predicate,
- Func thenFunc,
- Func elseFunc)
- => predicate(value) ? thenFunc(value) : elseFunc(value);
-
- ///
- /// As:类型转换(安全转换)
- ///
- /// 源类型的泛型参数
- /// 目标类型的泛型参数
- /// 要进行类型转换的值
- /// 转换后的值,如果转换失败则返回null
- public static TResult? As(
- this TSource value)
- where TResult : class
- => value as TResult;
-
- ///
- /// Cast:强制类型转换
- ///
- /// 目标类型的泛型参数
- /// 要进行类型转换的对象
- /// 强制转换后的值
- public static TResult Cast(
- this object value)
- => (TResult)value;
-
+
///
/// Also:执行操作并返回原值
///
@@ -287,94 +114,5 @@ public static class PipeExtensions
Func transform)
=> transform(value);
- ///
- /// TakeIf:条件返回值或null
- ///
- /// 输入值的类型
- /// 要进行条件判断的输入值
- /// 条件判断函数
- /// 条件为真时返回原值,否则返回null
- public static TSource? TakeIf(
- this TSource value,
- Func predicate)
- where TSource : class
- => predicate(value) ? value : null;
-
- ///
- /// TakeUnless:条件相反的TakeIf
- ///
- /// 输入值的类型
- /// 要进行条件判断的输入值
- /// 条件判断函数
- /// 条件为假时返回原值,否则返回null
- public static TSource? TakeUnless(
- this TSource value,
- Func predicate)
- where TSource : class
- => !predicate(value) ? value : null;
-
- ///
- /// Repeat:重复执行函数n次
- ///
- /// 输入值的类型
- /// 初始输入值
- /// 重复执行的次数
- /// 要重复执行的函数
- /// 经过多次变换后的最终值
- public static TSource Repeat(
- this TSource value,
- int times,
- Func func)
- {
- var result = value;
- for (int i = 0; i < times; i++)
- {
- result = func(result);
- }
- return result;
- }
-
- ///
- /// Try:安全执行,捕获异常
- ///
- /// 输入值的类型
- /// 函数返回结果的类型
- /// 要传递给函数的输入值
- /// 要安全执行的函数
- /// 包含执行状态、结果和错误信息的元组
- public static (bool success, TResult? result, Exception? error) Try(
- this TSource value,
- Func func)
- {
- try
- {
- return (true, func(value), null);
- }
- catch (Exception ex)
- {
- return (false, default, ex);
- }
- }
-
- ///
- /// Memoize:缓存函数结果
- ///
- /// 函数输入参数的类型
- /// 函数返回结果的类型
- /// 要缓存结果的函数
- /// 带有缓存功能的包装函数
- public static Func Memoize(
- this Func func)
- where TSource : notnull
- {
- var cache = new Dictionary();
- return x =>
- {
- if (cache.TryGetValue(x, out var result))
- return result;
- result = func(x);
- cache[x] = result;
- return result;
- };
- }
+
}
diff --git a/GFramework.Core/functional/types/TypeExtensions.cs b/GFramework.Core/functional/types/TypeExtensions.cs
new file mode 100644
index 0000000..937998f
--- /dev/null
+++ b/GFramework.Core/functional/types/TypeExtensions.cs
@@ -0,0 +1,44 @@
+// Copyright (c) 2025 GeWuYou
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+namespace GFramework.Core.functional.types;
+
+///
+/// 提供类型转换相关的扩展方法
+///
+public static class TypeExtensions
+{
+ ///
+ /// 安全类型转换方法,将源类型转换为目标类型
+ /// 如果转换失败或值为null,则返回null而不抛出异常
+ ///
+ /// 源类型参数
+ /// 目标类型参数,必须为引用类型
+ /// 需要进行类型转换的源值
+ /// 转换成功时返回目标类型实例,失败时返回null
+ public static TResult? As(
+ this TSource value)
+ where TResult : class
+ => value as TResult;
+
+ ///
+ /// 强制类型转换方法,将对象转换为指定的目标类型
+ /// 转换失败时会抛出InvalidCastException异常
+ ///
+ /// 目标类型参数
+ /// 需要进行强制类型转换的对象
+ /// 转换后的目标类型实例
+ /// 当转换失败时抛出此异常
+ public static TResult Cast(
+ this object value)
+ => (TResult)value;
+}