// 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. namespace GFramework.Core.functional; /// /// 表示可能存在或不存在的值,用于替代 null 引用的函数式编程类型 /// /// 值的类型 public readonly struct Option { private readonly T _value; private readonly bool _isSome; /// /// 私有构造函数,用于创建 Some 状态 /// private Option(T value) { _value = value; _isSome = true; } /// /// 判断是否有值 /// public bool IsSome => _isSome; /// /// 判断是否无值 /// public bool IsNone => !_isSome; #region 工厂方法 /// /// 创建包含值的 Option /// /// 要包装的值 /// 包含值的 Option /// 当 value 为 null 时抛出 /// /// /// var option = Option<int>.Some(42); /// /// public static Option Some(T value) { ArgumentNullException.ThrowIfNull(value); return new Option(value); } /// /// 表示无值的 Option /// public static Option None => default; #endregion #region 取值 /// /// 获取值,如果无值则返回默认值 /// /// 无值时返回的默认值 /// Option 中的值或默认值 /// /// /// var value = option.GetOrElse(0); // 如果无值则返回 0 /// /// public T GetOrElse(T defaultValue) => _isSome ? _value : defaultValue; /// /// 获取值,如果无值则通过工厂函数生成默认值 /// /// 生成默认值的工厂函数 /// Option 中的值或工厂函数生成的值 /// 当 factory 为 null 时抛出 /// /// /// var value = option.GetOrElse(() => ExpensiveDefault()); /// /// public T GetOrElse(Func factory) { ArgumentNullException.ThrowIfNull(factory); return _isSome ? _value : factory(); } #endregion #region 变换 /// /// 映射值到新类型,如果无值则返回 None /// /// 映射后的类型 /// 映射函数 /// 映射后的 Option /// 当 mapper 为 null 时抛出 /// /// /// var option = Option<int>.Some(42); /// var mapped = option.Map(x => x.ToString()); // Option<string>.Some("42") /// /// public Option Map(Func mapper) { ArgumentNullException.ThrowIfNull(mapper); return _isSome ? Option.Some(mapper(_value)) : Option.None; } /// /// 单子绑定操作,将 Option 链式转换 /// /// 绑定后的类型 /// 绑定函数 /// 绑定后的 Option /// 当 binder 为 null 时抛出 /// /// /// var option = Option<string>.Some("42"); /// var bound = option.Bind(s => int.TryParse(s, out var i) /// ? Option<int>.Some(i) /// : Option<int>.None); /// /// public Option Bind(Func> binder) { ArgumentNullException.ThrowIfNull(binder); return _isSome ? binder(_value) : Option.None; } #endregion #region 过滤 /// /// 根据条件过滤值,不满足条件则返回 None /// /// 过滤条件 /// 满足条件的 Option 或 None /// 当 predicate 为 null 时抛出 /// /// /// var option = Option<int>.Some(42); /// var filtered = option.Filter(x => x > 0); // Option<int>.Some(42) /// var filtered2 = option.Filter(x => x < 0); // Option<int>.None /// /// public Option Filter(Func predicate) { ArgumentNullException.ThrowIfNull(predicate); return _isSome && predicate(_value) ? this : None; } #endregion #region 模式匹配 /// /// 模式匹配,根据是否有值执行不同的函数 /// /// 返回值类型 /// 有值时执行的函数 /// 无值时执行的函数 /// 匹配结果 /// 当 some 或 none 为 null 时抛出 /// /// /// var result = option.Match( /// some: value => $"Value: {value}", /// none: () => "No value" /// ); /// /// public TResult Match(Func some, Func none) { ArgumentNullException.ThrowIfNull(some); ArgumentNullException.ThrowIfNull(none); return _isSome ? some(_value) : none(); } /// /// 模式匹配(副作用版本),根据是否有值执行不同的操作 /// /// 有值时执行的操作 /// 无值时执行的操作 /// 当 some 或 none 为 null 时抛出 /// /// /// option.Match( /// some: value => Console.WriteLine($"Value: {value}"), /// none: () => Console.WriteLine("No value") /// ); /// /// public void Match(Action some, Action none) { ArgumentNullException.ThrowIfNull(some); ArgumentNullException.ThrowIfNull(none); if (_isSome) some(_value); else none(); } #endregion #region 转换 /// /// 转换为 Result 类型 /// /// 无值时的错误消息 /// Result 类型 /// /// /// var result = option.ToResult("Value not found"); /// /// public Result ToResult(string errorMessage = "Value is None") { ArgumentException.ThrowIfNullOrWhiteSpace(errorMessage); return _isSome ? Result.Succeed(_value) : Result.Fail(new InvalidOperationException(errorMessage)); } /// /// 转换为可枚举集合(有值时包含一个元素,无值时为空集合) /// /// 可枚举集合 /// /// /// var items = option.ToEnumerable(); // 有值时: [value], 无值时: [] /// /// public IEnumerable ToEnumerable() { if (_isSome) yield return _value; } #endregion #region 隐式转换 /// /// 从值隐式转换为 Option /// public static implicit operator Option(T value) => value is not null ? Some(value) : None; #endregion #region 相等性和比较 /// /// 判断两个 Option 是否相等 /// public bool Equals(Option other) { if (_isSome != other._isSome) return false; return !_isSome || EqualityComparer.Default.Equals(_value, other._value); } /// /// 判断与对象是否相等 /// public override bool Equals(object? obj) => obj is Option other && Equals(other); /// /// 获取哈希码 /// public override int GetHashCode() => _isSome ? EqualityComparer.Default.GetHashCode(_value!) : 0; /// /// 相等运算符 /// public static bool operator ==(Option left, Option right) => left.Equals(right); /// /// 不等运算符 /// public static bool operator !=(Option left, Option right) => !left.Equals(right); #endregion #region 字符串表示 /// /// 获取字符串表示 /// public override string ToString() => _isSome ? $"Some({_value})" : "None"; #endregion }