using System; namespace Utils; /// /// "Nullable" wrapper. Can wrap both value types and reference types. /// /// public readonly struct Option : IEquatable> { public bool HasValue { get; } = false; private readonly T _value = default!; public Option() { } public Option(T value) { _value = value; HasValue = true; } public T Value { get { if (!HasValue) throw new InvalidOperationException("Cannot access value of None"); return _value; } } public bool Equals(Option other) { return (!HasValue && !other.HasValue) || (HasValue && other.HasValue && _value!.Equals(other._value)); } public override bool Equals(object obj) { if (obj is Option other) return Equals(other); return false; } public override int GetHashCode() { return HashCode.Combine(HasValue, _value); } public static bool operator ==(Option left, Option right) { return left.Equals(right); } public static bool operator !=(Option left, Option right) { return !(left == right); } public Option Map(Func map) { if (HasValue) return Option.Some(map(_value)); return Option.None(); } public T Or(T otherwise) { if (HasValue) return _value; return otherwise; } public Option Or(Option otherwise) { if (HasValue) return this; return otherwise; } } public static class Option { public static Option None() => default; public static Option Some(T value) => new(value); public static Option FromNullable(T? value) where T : struct { if (!value.HasValue) return default; return new(value.Value); } public static Option FromObject(T? value) { if (value is null) return default; return new(value); } }