// 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. using System.Diagnostics.Contracts; using System.Runtime.InteropServices; namespace GFramework.Core.Functional; /// /// 表示一个无值的操作结果,仅包含成功或失败状态 /// [StructLayout(LayoutKind.Auto)] public readonly struct Result : IEquatable { private readonly Exception? _exception; private readonly bool _isSuccess; /// /// 私有构造函数,用于创建 Result 实例 /// /// 是否为成功状态 /// 失败时的异常信息 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; } /// /// 判断结果是否为成功状态 /// [Pure] public bool IsSuccess => _isSuccess; /// /// 判断结果是否为失败状态 /// [Pure] public bool IsFailure => !_isSuccess; /// /// 获取失败时的异常信息,若为成功状态则抛出 InvalidOperationException /// [Pure] public Exception Error => IsFailure ? _exception! : throw new InvalidOperationException("Cannot access Error on a successful Result."); /// /// 创建成功结果 /// /// 成功结果 [Pure] public static Result Success() => new(true, null); /// /// 创建失败结果 /// /// 失败的异常 /// 失败结果 [Pure] public static Result Failure(Exception ex) { ArgumentNullException.ThrowIfNull(ex); return new(false, ex); } /// /// 根据错误消息创建失败结果 /// /// 错误消息 /// 失败结果 [Pure] public static Result Failure(string message) { ArgumentException.ThrowIfNullOrWhiteSpace(message); return new Result(false, new InvalidOperationException(message)); } /// /// 根据成功或失败状态分别执行不同的处理逻辑 /// /// 返回值类型 /// 成功时执行的函数 /// 失败时执行的函数 /// 处理后的结果 public R Match(Func onSuccess, Func onFailure) => IsSuccess ? onSuccess() : onFailure(_exception!); /// /// 将当前无值的 Result 提升为带值的 Result /// /// 值的类型 /// 成功时关联的值 /// 带值的 Result [Pure] public Result ToResult(A value) => IsSuccess ? Result.Success(value) : Result.Failure(_exception!); /// /// 判断当前 Result 是否与另一个 Result 相等 /// /// 另一个 Result /// 若相等返回 true,否则返回 false [Pure] public bool Equals(Result other) { if (_isSuccess != other._isSuccess) return false; if (_isSuccess) return true; return _exception!.GetType() == other._exception!.GetType() && _exception.Message == other._exception.Message; } /// /// 判断当前对象是否与另一个对象相等 /// /// 另一个对象 /// 若相等返回 true,否则返回 false [Pure] public override bool Equals(object? obj) => obj is Result other && Equals(other); /// /// 获取当前 Result 的哈希码 /// /// 哈希码 [Pure] public override int GetHashCode() { return _isSuccess ? 1 : HashCode.Combine(_exception!.GetType(), _exception.Message); } /// /// 判断两个 Result 是否相等 /// /// 第一个 Result /// 第二个 Result /// 若相等返回 true,否则返回 false [Pure] public static bool operator ==(Result a, Result b) => a.Equals(b); /// /// 判断两个 Result 是否不相等 /// /// 第一个 Result /// 第二个 Result /// 若不相等返回 true,否则返回 false [Pure] public static bool operator !=(Result a, Result b) => !a.Equals(b); /// /// 返回当前 Result 的字符串表示 /// /// Result 的字符串表示 [Pure] public override string ToString() => _isSuccess ? "Success" : $"Fail({_exception!.Message})"; /// /// 尝试执行一个无返回值的操作,并根据执行结果返回成功或失败的 Result /// /// 要执行的无返回值操作 /// 若操作成功执行返回成功的 Result,若执行过程中抛出异常则返回失败的 Result [Pure] public static Result Try(Action action) { ArgumentNullException.ThrowIfNull(action); try { action(); return Success(); } catch (Exception ex) { return Failure(ex); } } /// /// 将当前 Result 的成功结果映射为另一种类型的 Result /// /// 映射后的目标类型 /// 用于转换值的函数 /// 若当前为成功状态,返回包含转换后值的成功 Result;若为失败状态,返回保持原有错误的失败 Result public Result Map(Func func) { ArgumentNullException.ThrowIfNull(func); return IsSuccess ? Result.Success(func()) : Result.Failure(_exception!); } /// /// 将当前 Result 绑定到一个返回 Result 的函数上 /// /// Result 中值的类型 /// 返回 Result 的函数 /// 若当前为成功状态,返回函数执行的结果;若为失败状态,返回保持原有错误的失败 Result public Result Bind(Func> func) { ArgumentNullException.ThrowIfNull(func); return IsSuccess ? func() : Result.Failure(_exception!); } }