From c9dd969b054466c1e677ff308ef101b967b7d0ea Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 31 Jan 2026 21:31:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(functional):=20=E6=B7=BB=E5=8A=A0Result?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=8F=8A=E5=85=B6=E6=89=A9=E5=B1=95=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入Result结构体用于表示可能成功或失败的计算结果 - 实现Result类型的Success和Failure静态工厂方法 - 添加SuccessValue和ErrorValue属性用于获取对应值 - 创建ResultExtensions扩展类提供Map、Bind、MapError和Match方法 - 在FunctionExtensions中添加TryResult方法将异常安全执行封装为Result类型 - 更新Try方法的文档注释以反映新的功能和返回类型 --- .../functions/FunctionExtensions.cs | 21 +++-- GFramework.Core/functional/types/Result.cs | 91 +++++++++++++++++++ .../functional/types/ResultExtensions.cs | 54 +++++++++++ 3 files changed, 158 insertions(+), 8 deletions(-) create mode 100644 GFramework.Core/functional/types/Result.cs create mode 100644 GFramework.Core/functional/types/ResultExtensions.cs diff --git a/GFramework.Core/functional/functions/FunctionExtensions.cs b/GFramework.Core/functional/functions/FunctionExtensions.cs index ff2d1c1..60acc0e 100644 --- a/GFramework.Core/functional/functions/FunctionExtensions.cs +++ b/GFramework.Core/functional/functions/FunctionExtensions.cs @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +using GFramework.Core.functional.types; + namespace GFramework.Core.functional.functions; /// @@ -79,28 +81,31 @@ public static class FunctionExtensions return result; } + /// - /// Try:安全执行,捕获异常 + /// 尝试执行一个转换函数,并将结果包装在Result对象中,捕获可能发生的异常 /// /// 输入值的类型 - /// 函数返回结果的类型 - /// 要传递给函数的输入值 - /// 要安全执行的函数 - /// 包含执行状态、结果和错误信息的元组 - public static (bool success, TResult? result, Exception? error) Try( + /// 转换函数返回值的类型 + /// 要进行转换操作的源值 + /// 用于转换源值的函数委托 + /// 如果转换成功则返回包含结果的成功状态,如果发生异常则返回包含异常信息的失败状态 + public static Result TryResult( this TSource value, Func func) { + // 执行转换函数并处理可能的异常 try { - return (true, func(value), null); + return Result.Success(func(value)); } catch (Exception ex) { - return (false, default, ex); + return Result.Failure(ex); } } + /// /// Memoize:缓存函数结果 /// diff --git a/GFramework.Core/functional/types/Result.cs b/GFramework.Core/functional/types/Result.cs new file mode 100644 index 0000000..8208da8 --- /dev/null +++ b/GFramework.Core/functional/types/Result.cs @@ -0,0 +1,91 @@ +// Copyright (c) 2026 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 readonly struct Result +{ + private readonly TSuccess _success; + private readonly TError _error; + + /// + /// 获取当前结果是否为成功状态 + /// + public bool IsSuccess { get; } + + /// + /// 获取当前结果是否为失败状态 + /// + public bool IsFailure => !IsSuccess; + + /// + /// 使用成功值初始化Result实例 + /// + /// 成功值 + private Result(TSuccess success) + { + _success = success; + _error = default!; + IsSuccess = true; + } + + /// + /// 使用错误值初始化Result实例 + /// + /// 错误值 + private Result(TError error) + { + _error = error; + _success = default!; + IsSuccess = false; + } + + /// + /// 创建一个表示成功的Result实例 + /// + /// 成功值 + /// 包含成功值的Result实例 + public static Result Success(TSuccess value) + => new(value); + + /// + /// 创建一个表示失败的Result实例 + /// + /// 错误值 + /// 包含错误值的Result实例 + public static Result Failure(TError error) + => new(error); + + /// + /// 获取成功值,如果结果为失败则抛出异常 + /// + /// 当结果为失败时抛出 + public TSuccess SuccessValue => + IsSuccess + ? _success + : throw new InvalidOperationException("Result is Failure"); + + /// + /// 获取错误值,如果结果为成功则抛出异常 + /// + /// 当结果为成功时抛出 + public TError ErrorValue => + IsFailure + ? _error + : throw new InvalidOperationException("Result is Success"); +} \ No newline at end of file diff --git a/GFramework.Core/functional/types/ResultExtensions.cs b/GFramework.Core/functional/types/ResultExtensions.cs new file mode 100644 index 0000000..a449cee --- /dev/null +++ b/GFramework.Core/functional/types/ResultExtensions.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2026 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 ResultExtensions +{ + public static Result Map( + this Result result, + Func mapper) + { + return result.IsSuccess + ? Result.Success(mapper(result.SuccessValue)) + : Result.Failure(result.ErrorValue); + } + + public static Result Bind( + this Result result, + Func> binder) + { + return result.IsSuccess + ? binder(result.SuccessValue) + : Result.Failure(result.ErrorValue); + } + + public static Result MapError( + this Result result, + Func mapper) + { + return result.IsFailure + ? Result.Failure(mapper(result.ErrorValue)) + : Result.Success(result.SuccessValue); + } + + public static TResult Match( + this Result result, + Func onSuccess, + Func onFailure) + { + return result.IsSuccess + ? onSuccess(result.SuccessValue) + : onFailure(result.ErrorValue); + } +} \ No newline at end of file