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