using System.Diagnostics.CodeAnalysis; namespace MS.Microservice.Core.Functional { /// /// Either 的 Left 容器,按约定表示错误分支。 /// public readonly struct Left { internal L Value { get; } internal Left(L value) { ArgumentNullException.ThrowIfNull(value, nameof(value)); Value = value; } public override string ToString() => $"Left({Value})"; } /// /// Either 的 Right 容器,按约定表示成功分支。 /// public readonly struct Right { internal R Value { get; } internal Right(R value) { ArgumentNullException.ThrowIfNull(value, nameof(value)); Value = value; } public override string ToString() => $"Right({Value})"; } /// /// 表示两种可能输出之一:Left(错误) 或 Right(成功)。 /// public readonly struct Either : IEquatable> { private readonly L? _left; private readonly R? _right; private readonly bool _isRight; private Either(L left) { _left = left; _right = default; _isRight = false; } private Either(R right) { _left = default; _right = right; _isRight = true; } [MemberNotNullWhen(true, nameof(_right))] [MemberNotNullWhen(false, nameof(_left))] public bool IsRight => _isRight; public bool IsLeft => !_isRight; public L Left => IsLeft ? _left! : throw new InvalidOperationException("Either 处于 Right 状态,无法读取 Left。"); public R Right => IsRight ? _right! : throw new InvalidOperationException("Either 处于 Left 状态,无法读取 Right。"); public static implicit operator Either(Left left) => new(left.Value); public static implicit operator Either(Right right) => new(right.Value); public T Match(Func left, Func right) => IsRight ? right(_right!) : left(_left!); public bool Equals(Either other) { if (IsLeft && other.IsLeft) { return EqualityComparer.Default.Equals(_left, other._left); } if (IsRight && other.IsRight) { return EqualityComparer.Default.Equals(_right, other._right); } return false; } public override bool Equals(object? obj) => obj is Either other && Equals(other); public override int GetHashCode() => IsRight ? HashCode.Combine(true, _right) : HashCode.Combine(false, _left); public override string ToString() => IsRight ? $"Right({_right})" : $"Left({_left})"; public static bool operator ==(Either left, Either right) => left.Equals(right); public static bool operator !=(Either left, Either right) => !left.Equals(right); } }