GeWuYou 1cb7dfdb14 feat(functional): 添加函数式编程支持和Result类型实现
- 实现了Result和Result<T>结构体,提供函数式错误处理
- 添加了AsyncExtensions中的函数式编程命名空间引用
- 在FunctionExtensions中添加函数式编程相关引用
- 从项目文件中移除LanguageExt.Core依赖包
- 重构GlobalUsings.cs移除不必要的全局引用
- 添加ResultExtensions扩展方法支持函数式操作
- 实现Map、Bind、Match等核心函数式编程方法
- 添加异步操作支持和安全执行委托功能
2026-02-25 20:21:37 +08:00

376 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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;
namespace GFramework.Core.Functional;
/// <summary>
/// 表示一个操作的结果,可能是成功值或异常
/// </summary>
public readonly struct Result<A> : IEquatable<Result<A>>, IComparable<Result<A>>
{
private readonly A? _value;
private readonly Exception? _exception;
// ------------------------------------------------------------------ 状态枚举
/// <summary>
/// 结果状态枚举,表示结果的不同状态
/// </summary>
private enum ResultState : byte
{
Bottom,
Success,
Faulted
}
private readonly ResultState _state;
// ------------------------------------------------------------------ 静态默认值
/// <summary>
/// 表示未初始化的 Bottom 状态
/// </summary>
public static readonly Result<A> Bottom = default;
// ------------------------------------------------------------------ 构造器
/// <summary>
/// 构造成功结果
/// </summary>
/// <param name="value">成功的值</param>
public Result(A value)
{
_state = ResultState.Success;
_value = value;
_exception = null;
}
/// <summary>
/// 构造失败结果
/// </summary>
/// <param name="exception">失败的异常</param>
public Result(Exception exception)
{
_state = ResultState.Faulted;
_exception = exception ?? throw new ArgumentNullException(nameof(exception));
_value = default;
}
// ------------------------------------------------------------------ 隐式转换
/// <summary>
/// 隐式将值转换为成功结果
/// </summary>
/// <param name="value">要转换的值</param>
/// <returns>成功结果</returns>
[Pure]
public static implicit operator Result<A>(A value) => new(value);
// ------------------------------------------------------------------ 状态属性
/// <summary>
/// 判断结果是否为成功状态
/// </summary>
[Pure]
public bool IsSuccess => _state == ResultState.Success;
/// <summary>
/// 判断结果是否为失败状态
/// </summary>
[Pure]
public bool IsFaulted => _state == ResultState.Faulted;
/// <summary>
/// 判断结果是否为未初始化的 Bottom 状态
/// </summary>
[Pure]
public bool IsBottom => _state == ResultState.Bottom;
/// <summary>
/// 获取内部异常,若为 Bottom 状态则抛出 InvalidOperationException
/// </summary>
[Pure]
public Exception Exception => _exception
?? new InvalidOperationException("Result is in Bottom state.");
// ------------------------------------------------------------------ 取值
/// <summary>
/// 若成功则返回值,若失败则返回默认值
/// </summary>
/// <param name="defaultValue">失败时返回的默认值</param>
/// <returns>成功时的值或默认值</returns>
[Pure]
public A IfFail(A defaultValue) => IsSuccess ? _value! : defaultValue;
/// <summary>
/// 若成功则返回值,若失败则通过委托处理异常
/// </summary>
/// <param name="f">处理异常的委托</param>
/// <returns>成功时的值或委托处理后的结果</returns>
[Pure]
public A IfFail(Func<Exception, A> f) => IsSuccess ? _value! : f(Exception);
/// <summary>
/// 若失败则执行副作用
/// </summary>
/// <param name="f">处理异常的副作用委托</param>
public void IfFail(Action<Exception> f)
{
if (IsFaulted) f(Exception);
}
/// <summary>
/// 若成功则执行副作用
/// </summary>
/// <param name="f">处理成功值的副作用委托</param>
public void IfSucc(Action<A> f)
{
if (IsSuccess) f(_value!);
}
// ------------------------------------------------------------------ 变换
/// <summary>
/// 成功时映射值,失败时透传异常
/// </summary>
/// <typeparam name="B">映射后的类型</typeparam>
/// <param name="f">映射函数</param>
/// <returns>映射后的结果</returns>
[Pure]
public Result<B> Map<B>(Func<A, B> f) =>
IsSuccess ? new Result<B>(f(_value!)) : new Result<B>(Exception);
/// <summary>
/// 成功时绑定到新 Result失败时透传异常
/// </summary>
/// <typeparam name="B">绑定后的类型</typeparam>
/// <param name="binder">绑定函数</param>
/// <returns>绑定后的结果</returns>
[Pure]
public Result<B> Bind<B>(Func<A, Result<B>> binder) =>
IsSuccess ? binder(_value!) : new Result<B>(Exception);
/// <summary>
/// 异步映射
/// </summary>
/// <typeparam name="B">映射后的类型</typeparam>
/// <param name="f">异步映射函数</param>
/// <returns>异步映射后的结果</returns>
[Pure]
public async Task<Result<B>> MapAsync<B>(Func<A, Task<B>> f) =>
IsSuccess ? new Result<B>(await f(_value!)) : new Result<B>(Exception);
// ------------------------------------------------------------------ 模式匹配
/// <summary>
/// 对成功/失败两种情况分别处理并返回值
/// </summary>
/// <typeparam name="R">返回值类型</typeparam>
/// <param name="succ">处理成功值的函数</param>
/// <param name="fail">处理异常的函数</param>
/// <returns>处理后的结果</returns>
[Pure]
public R Match<R>(Func<A, R> succ, Func<Exception, R> fail) =>
IsSuccess ? succ(_value!) : fail(Exception);
/// <summary>
/// 对成功/失败两种情况分别执行副作用
/// </summary>
/// <param name="succ">处理成功值的副作用委托</param>
/// <param name="fail">处理异常的副作用委托</param>
public void Match(Action<A> succ, Action<Exception> fail)
{
if (IsSuccess) succ(_value!);
else fail(Exception);
}
// ------------------------------------------------------------------ 静态工厂(语义更清晰)
/// <summary>
/// 创建成功结果
/// </summary>
/// <param name="value">成功的值</param>
/// <returns>成功结果</returns>
[Pure]
public static Result<A> Succeed(A value) => new(value);
/// <summary>
/// 创建成功结果(别名)
/// </summary>
/// <param name="value">成功的值</param>
/// <returns>成功结果</returns>
[Pure]
public static Result<A> Success(A value) => new(value);
/// <summary>
/// 创建失败结果
/// </summary>
/// <param name="ex">失败的异常</param>
/// <returns>失败结果</returns>
[Pure]
public static Result<A> Fail(Exception ex) => new(ex);
/// <summary>
/// 创建失败结果(别名)
/// </summary>
/// <param name="ex">失败的异常</param>
/// <returns>失败结果</returns>
[Pure]
public static Result<A> Failure(Exception ex) => new(ex);
/// <summary>
/// 根据错误消息创建失败结果
/// </summary>
/// <param name="message">错误消息</param>
/// <returns>失败结果</returns>
[Pure]
public static Result<A> Failure(string message) => new(new Exception(message));
/// <summary>
/// 安全执行委托,自动捕获异常
/// </summary>
/// <param name="f">要执行的委托</param>
/// <returns>执行结果</returns>
public static Result<A> Try(Func<A> f)
{
try
{
return new Result<A>(f());
}
catch (Exception ex)
{
return new Result<A>(ex);
}
}
// ------------------------------------------------------------------ 相等 / 比较
/// <summary>
/// 判断两个结果是否相等
/// </summary>
/// <param name="other">另一个结果</param>
/// <returns>若相等返回 true否则返回 false</returns>
[Pure]
public bool Equals(Result<A> other)
{
if (_state != other._state) return false;
if (IsSuccess) return EqualityComparer<A>.Default.Equals(_value, other._value);
if (IsFaulted)
return Exception.GetType() == other.Exception.GetType()
&& Exception.Message == other.Exception.Message;
return true; // both Bottom
}
/// <summary>
/// 判断对象是否与当前结果相等
/// </summary>
/// <param name="obj">要比较的对象</param>
/// <returns>若相等返回 true否则返回 false</returns>
[Pure]
public override bool Equals(object? obj) => obj is Result<A> other && Equals(other);
/// <summary>
/// 获取结果的哈希码
/// </summary>
/// <returns>哈希码</returns>
[Pure]
public override int GetHashCode() => IsSuccess
? HashCode.Combine(0, _value)
: HashCode.Combine(1, Exception.GetType(), Exception.Message);
/// <summary>
/// 比较两个结果的大小
/// </summary>
/// <param name="other">另一个结果</param>
/// <returns>比较结果</returns>
[Pure]
public int CompareTo(Result<A> other)
{
// Bottom < Faulted < Success
if (_state != other._state) return _state.CompareTo(other._state);
if (!IsSuccess) return 0;
return Comparer<A>.Default.Compare(_value, other._value);
}
/// <summary>
/// 判断两个结果是否相等
/// </summary>
/// <param name="a">第一个结果</param>
/// <param name="b">第二个结果</param>
/// <returns>若相等返回 true否则返回 false</returns>
[Pure]
public static bool operator ==(Result<A> a, Result<A> b) => a.Equals(b);
/// <summary>
/// 判断两个结果是否不相等
/// </summary>
/// <param name="a">第一个结果</param>
/// <param name="b">第二个结果</param>
/// <returns>若不相等返回 true否则返回 false</returns>
[Pure]
public static bool operator !=(Result<A> a, Result<A> b) => !a.Equals(b);
/// <summary>
/// 判断第一个结果是否小于第二个结果
/// </summary>
/// <param name="a">第一个结果</param>
/// <param name="b">第二个结果</param>
/// <returns>若小于返回 true否则返回 false</returns>
[Pure]
public static bool operator <(Result<A> a, Result<A> b) => a.CompareTo(b) < 0;
/// <summary>
/// 判断第一个结果是否小于等于第二个结果
/// </summary>
/// <param name="a">第一个结果</param>
/// <param name="b">第二个结果</param>
/// <returns>若小于等于返回 true否则返回 false</returns>
[Pure]
public static bool operator <=(Result<A> a, Result<A> b) => a.CompareTo(b) <= 0;
/// <summary>
/// 判断第一个结果是否大于第二个结果
/// </summary>
/// <param name="a">第一个结果</param>
/// <param name="b">第二个结果</param>
/// <returns>若大于返回 true否则返回 false</returns>
[Pure]
public static bool operator >(Result<A> a, Result<A> b) => a.CompareTo(b) > 0;
/// <summary>
/// 判断第一个结果是否大于等于第二个结果
/// </summary>
/// <param name="a">第一个结果</param>
/// <param name="b">第二个结果</param>
/// <returns>若大于等于返回 true否则返回 false</returns>
[Pure]
public static bool operator >=(Result<A> a, Result<A> b) => a.CompareTo(b) >= 0;
// ------------------------------------------------------------------ 调试
/// <summary>
/// 返回结果的字符串表示
/// </summary>
/// <returns>结果的字符串表示</returns>
[Pure]
public override string ToString() => _state switch
{
ResultState.Success => _value?.ToString() ?? "(null)",
ResultState.Faulted => $"Fail({Exception.Message})",
_ => "(Bottom)"
};
}