From 47509106758ea4d8aa2646d552afaa3d63ffa13b Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Tue, 10 Mar 2026 19:20:52 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(Result):=20=E6=89=A9=E5=B1=95Result?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BD=93=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加StructLayout特性优化内存布局 - 将Failure方法中的Exception替换为InvalidOperationException - 重构Equals方法提高比较逻辑的可读性 - 简化GetHashCode方法的哈希计算逻辑 - 更新ToString方法移除空值检查 - 新增Try方法用于安全执行可能抛出异常的操作 - 添加Map方法支持将Result成功状态映射到其他类型 - 实现Bind方法用于链式调用Result操作 --- GFramework.Core/Functional/Result.cs | 60 +++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/GFramework.Core/Functional/Result.cs b/GFramework.Core/Functional/Result.cs index 03508b5..2763a9d 100644 --- a/GFramework.Core/Functional/Result.cs +++ b/GFramework.Core/Functional/Result.cs @@ -12,12 +12,14 @@ // limitations under the License. using System.Diagnostics.Contracts; +using System.Runtime.InteropServices; namespace GFramework.Core.Functional; /// /// 表示一个无值的操作结果,仅包含成功或失败状态 /// +[StructLayout(LayoutKind.Auto)] public readonly struct Result : IEquatable { private readonly Exception? _exception; @@ -82,7 +84,7 @@ public readonly struct Result : IEquatable public static Result Failure(string message) { ArgumentException.ThrowIfNullOrWhiteSpace(message); - return new(false, new Exception(message)); + return new Result(false, new InvalidOperationException(message)); } /// @@ -113,10 +115,14 @@ public readonly struct Result : IEquatable [Pure] public bool Equals(Result other) { - // 比较状态和异常信息 - return _isSuccess == other._isSuccess && - (!IsFailure || (_exception?.GetType() == other._exception?.GetType() && - _exception?.Message == other._exception?.Message)); + if (_isSuccess != other._isSuccess) + return false; + + if (_isSuccess) + return true; + + return _exception!.GetType() == other._exception!.GetType() && + _exception.Message == other._exception.Message; } /// @@ -134,10 +140,7 @@ public readonly struct Result : IEquatable [Pure] public override int GetHashCode() { - // 根据状态和异常信息生成哈希码 - return IsSuccess - ? HashCode.Combine(true) - : HashCode.Combine(false, _exception?.GetType(), _exception?.Message); + return _isSuccess ? 1 : HashCode.Combine(_exception!.GetType(), _exception.Message); } /// @@ -164,5 +167,42 @@ public readonly struct Result : IEquatable /// Result 的字符串表示 [Pure] public override string ToString() => - IsSuccess ? "Success" : $"Fail({_exception?.Message ?? "Unknown"})"; + _isSuccess ? "Success" : $"Fail({_exception!.Message})"; + + /// + /// 尝试执行一个无返回值的操作,并根据执行结果返回成功或失败的 Result + /// + /// 要执行的无返回值操作 + /// 若操作成功执行返回成功的 Result,若执行过程中抛出异常则返回失败的 Result + [Pure] + public static Result Try(Action action) + { + try + { + action(); + return Success(); + } + catch (Exception ex) + { + return Failure(ex); + } + } + + /// + /// 将当前 Result 的成功结果映射为另一种类型的 Result + /// + /// 映射后的目标类型 + /// 用于转换值的函数 + /// 若当前为成功状态,返回包含转换后值的成功 Result;若为失败状态,返回保持原有错误的失败 Result + public Result Map(Func func) => + IsSuccess ? Result.Success(func()) : Result.Failure(_exception!); + + /// + /// 将当前 Result 绑定到一个返回 Result 的函数上 + /// + /// Result 中值的类型 + /// 返回 Result 的函数 + /// 若当前为成功状态,返回函数执行的结果;若为失败状态,返回保持原有错误的失败 Result + public Result Bind(Func> func) => + IsSuccess ? func() : Result.Failure(_exception!); } \ No newline at end of file From c6024bf94a272d617f81357bb6568bb6724f87ce Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Tue, 10 Mar 2026 21:09:58 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat(GFramework.Core.Functional.Result):=20?= =?UTF-8?q?=E5=A2=9E=E5=BC=BAResult=E7=B1=BB=E7=9A=84=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E6=80=A7=E5=92=8C=E5=81=A5=E5=A3=AE=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在构造函数中添加强制不变式检查,确保失败状态必须携带非空异常 - 为Try方法添加空值验证,防止传入空委托导致异常 - 为Map方法添加空值验证,增强方法调用的安全性 - 为Bind方法添加空值验证,提升代码健壮性 - 重构Map和Bind方法结构,使其更清晰易读 --- GFramework.Core/Functional/Result.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/GFramework.Core/Functional/Result.cs b/GFramework.Core/Functional/Result.cs index 2763a9d..994df5f 100644 --- a/GFramework.Core/Functional/Result.cs +++ b/GFramework.Core/Functional/Result.cs @@ -32,6 +32,10 @@ public readonly struct Result : IEquatable /// 失败时的异常信息 private Result(bool isSuccess, Exception? exception) { + // 强制不变式:失败状态必须携带非空异常 + if (!isSuccess && exception is null) + throw new ArgumentException("Failure Result must have a non-null exception.", nameof(exception)); + _isSuccess = isSuccess; _exception = exception; } @@ -177,6 +181,7 @@ public readonly struct Result : IEquatable [Pure] public static Result Try(Action action) { + ArgumentNullException.ThrowIfNull(action); try { action(); @@ -194,8 +199,11 @@ public readonly struct Result : IEquatable /// 映射后的目标类型 /// 用于转换值的函数 /// 若当前为成功状态,返回包含转换后值的成功 Result;若为失败状态,返回保持原有错误的失败 Result - public Result Map(Func func) => - IsSuccess ? Result.Success(func()) : Result.Failure(_exception!); + public Result Map(Func func) + { + ArgumentNullException.ThrowIfNull(func); + return IsSuccess ? Result.Success(func()) : Result.Failure(_exception!); + } /// /// 将当前 Result 绑定到一个返回 Result 的函数上 @@ -203,6 +211,9 @@ public readonly struct Result : IEquatable /// Result 中值的类型 /// 返回 Result 的函数 /// 若当前为成功状态,返回函数执行的结果;若为失败状态,返回保持原有错误的失败 Result - public Result Bind(Func> func) => - IsSuccess ? func() : Result.Failure(_exception!); + public Result Bind(Func> func) + { + ArgumentNullException.ThrowIfNull(func); + return IsSuccess ? func() : Result.Failure(_exception!); + } } \ No newline at end of file