using System.Reflection; using System.Collections; using System.Diagnostics; namespace System { struct Nullable where T : struct { T mValue; bool mHasValue; public this(T value) { mHasValue = true; mValue = value; } public bool HasValue { [Inline] get { return mHasValue; } } public T Value { [Inline] get { if (!mHasValue) { Debug.FatalError("Value requested for null nullable."); } return mValue; } } public ref T ValueRef { [Inline] get mut { if (!mHasValue) { Debug.FatalError("Value requested for null nullable."); } return ref mValue; } } public T GetValueOrDefault() { return mValue; } public bool TryGetValue(ref T outValue) { if (!mHasValue) return false; outValue = mValue; return true; } public T GetValueOrDefault(T defaultmValue) { return mHasValue ? mValue : defaultmValue; } public override void ToString(String str) { if (mHasValue) mValue.ToString(str); else str.Clear(); } [Inline] public static implicit operator Nullable(T value) { Nullable result; result.mHasValue = true; result.mValue = value; return result; } [Inline] public static explicit operator T(Nullable value) { return value.mValue; } [Inline] public static bool operator==(Nullable lhs, T rhs) { if (!lhs.mHasValue) return false; return lhs.mValue == rhs; } /// public static bool operator==(Nullable lhs, TOther rhs) where bool : operator T == TOther { if (!lhs.mHasValue) return false; return lhs.mValue == rhs; } public static bool operator==(TOther lhs, Nullable rhs) where bool : operator TOther == T { if (!rhs.mHasValue) return false; return lhs == rhs.mValue; } public static bool operator==(Nullable lhs, Nullable rhs) where bool : operator T == TOther where TOther : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return !lhs.mHasValue && !rhs.mHasValue; // Only both being null results in 'true' return lhs.mValue == rhs.mValue; } /// public static bool operator!=(Nullable lhs, TOther rhs) where bool : operator T != TOther { if (!lhs.mHasValue) return true; return lhs.mValue != rhs; } public static bool operator!=(TOther lhs, Nullable rhs) where bool : operator TOther != T { if (!rhs.mHasValue) return true; return lhs != rhs.mValue; } public static bool operator!=(Nullable lhs, Nullable rhs) where bool : operator T != TOther where TOther : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return !(!lhs.mHasValue && !rhs.mHasValue); // Only both being null results in 'false' return lhs.mValue != rhs.mValue; } /// public static bool operator< (Nullable lhs, TOther rhs) where bool : operator T < TOther { if (!lhs.mHasValue) return false; return lhs.mValue < rhs; } public static bool operator< (TOther lhs, Nullable rhs) where bool : operator TOther < T { if (!rhs.mHasValue) return false; return lhs < rhs.mValue; } public static bool operator< (Nullable lhs, Nullable rhs) where bool : operator T < TOther where TOther : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return false; return lhs.mValue < rhs.mValue; } /// public static bool operator<=(Nullable lhs, TOther rhs) where bool : operator T <= TOther { if (!lhs.mHasValue) return false; return lhs.mValue <= rhs; } public static bool operator<=(TOther lhs, Nullable rhs) where bool : operator TOther <= T { if (!rhs.mHasValue) return false; return lhs <= rhs.mValue; } public static bool operator<=(Nullable lhs, Nullable rhs) where bool : operator T <= TOther where TOther : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return false; return lhs.mValue <= rhs.mValue; } /// public static bool operator>(Nullable lhs, TOther rhs) where bool : operator T > TOther { if (!lhs.mHasValue) return false; return lhs.mValue > rhs; } public static bool operator>(TOther lhs, Nullable rhs) where bool : operator TOther > T { if (!rhs.mHasValue) return false; return lhs > rhs.mValue; } public static bool operator>(Nullable lhs, Nullable rhs) where bool : operator T > TOther where TOther : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return false; return lhs.mValue > rhs.mValue; } /// public static bool operator>=(Nullable lhs, TOther rhs) where bool : operator T >= TOther { if (!lhs.mHasValue) return false; return lhs.mValue >= rhs; } public static bool operator>=(TOther lhs, Nullable rhs) where bool : operator TOther >= T { if (!rhs.mHasValue) return false; return lhs >= rhs.mValue; } public static bool operator>=(Nullable lhs, Nullable rhs) where bool : operator T >= TOther where TOther : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return false; return lhs.mValue >= rhs.mValue; } /// public static int operator<=>(Nullable lhs, TOther rhs) where int : operator T <=> TOther { return lhs.mValue <=> rhs; } public static int operator<=>(TOther lhs, Nullable rhs) where int : operator TOther <=> T { return lhs <=> rhs.mValue; } public static int operator<=>(Nullable lhs, Nullable rhs) where int : operator T <=> TOther where TOther : struct { return lhs.mValue <=> rhs.mValue; } /// public static TResult? operator+(Nullable lhs, TOther rhs) where TResult = operator T + TOther where TResult : struct { if (!lhs.mHasValue) return null; return Nullable(lhs.mValue + rhs); } public static TResult? operator+(TOther lhs, Nullable rhs) where TResult = operator TOther + T where TResult : struct { if (!rhs.mHasValue) return null; return Nullable(lhs + rhs.mValue); } public static TResult? operator+(Nullable lhs, Nullable rhs) where TOther : struct where TResult = operator T + TOther where TResult : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return null; return Nullable(lhs.mValue + rhs.mValue); } /// public static TResult? operator-(TOther lhs, Nullable rhs) where TResult = operator TOther - T where TResult : struct { if (!rhs.mHasValue) return null; return Nullable(lhs - rhs.mValue); } public static TResult? operator-(Nullable lhs, TOther rhs) where TResult = operator T - TOther where TResult : struct { if (!lhs.mHasValue) return null; return Nullable(lhs.mValue - rhs); } public static TResult? operator-(Nullable lhs, Nullable rhs) where TOther : struct where TResult = operator T - TOther where TResult : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return null; return Nullable(lhs.mValue - rhs.mValue); } // public static TResult? operator*(TOther lhs, Nullable rhs) where TResult = operator TOther * T where TResult : struct { if (!rhs.mHasValue) return null; return Nullable(lhs * rhs.mValue); } public static TResult? operator*(Nullable lhs, TOther rhs) where TResult = operator T * TOther where TResult : struct { if (!lhs.mHasValue) return null; return Nullable(lhs.mValue * rhs); } public static TResult? operator*(Nullable lhs, Nullable rhs) where TOther : struct where TResult = operator T * TOther where TResult : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return null; return Nullable(lhs.mValue * rhs.mValue); } // public static TResult? operator/(TOther lhs, Nullable rhs) where TResult = operator TOther / T where TResult : struct { if (!rhs.mHasValue) return null; return Nullable(lhs / rhs.mValue); } public static TResult? operator/(Nullable lhs, TOther rhs) where TResult = operator T / TOther where TResult : struct { if (!lhs.mHasValue) return null; return Nullable(lhs.mValue / rhs); } public static TResult? operator/(Nullable lhs, Nullable rhs) where TOther : struct where TResult = operator T / TOther where TResult : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return null; return Nullable(lhs.mValue / rhs.mValue); } // public static TResult? operator%(TOther lhs, Nullable rhs) where TResult = operator TOther % T where TResult : struct { if (!rhs.mHasValue) return null; return Nullable(lhs % rhs.mValue); } public static TResult? operator%(Nullable lhs, TOther rhs) where TResult = operator T % TOther where TResult : struct { if (!lhs.mHasValue) return null; return Nullable(lhs.mValue % rhs); } public static TResult? operator%(Nullable lhs, Nullable rhs) where TOther : struct where TResult = operator T % TOther where TResult : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return null; return Nullable(lhs.mValue % rhs.mValue); } // public static TResult? operator^(TOther lhs, Nullable rhs) where TResult = operator TOther ^ T where TResult : struct { if (!rhs.mHasValue) return null; return Nullable(lhs ^ rhs.mValue); } public static TResult? operator^(Nullable lhs, TOther rhs) where TResult = operator T ^ TOther where TResult : struct { if (!lhs.mHasValue) return null; return Nullable(lhs.mValue ^ rhs); } public static TResult? operator^(Nullable lhs, Nullable rhs) where TOther : struct where TResult = operator T ^ TOther where TResult : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return null; return Nullable(lhs.mValue ^ rhs.mValue); } // public static TResult? operator&(TOther lhs, Nullable rhs) where TResult = operator TOther & T where TResult : struct { if (!rhs.mHasValue) return null; return Nullable(lhs & rhs.mValue); } public static TResult? operator&(Nullable lhs, TOther rhs) where TResult = operator T & TOther where TResult : struct { if (!lhs.mHasValue) return null; return Nullable(lhs.mValue & rhs); } public static TResult? operator&(Nullable lhs, Nullable rhs) where TOther : struct where TResult = operator T & TOther where TResult : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return null; return Nullable(lhs.mValue & rhs.mValue); } // public static TResult? operator|(TOther lhs, Nullable rhs) where TResult = operator TOther | T where TResult : struct { if (!rhs.mHasValue) return null; return Nullable(lhs | rhs.mValue); } public static TResult? operator|(Nullable lhs, TOther rhs) where TResult = operator T | TOther where TResult : struct { if (!lhs.mHasValue) return null; return Nullable(lhs.mValue | rhs); } public static TResult? operator|(Nullable lhs, Nullable rhs) where TOther : struct where TResult = operator T | TOther where TResult : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return null; return Nullable(lhs.mValue | rhs.mValue); } // public static T operator??(Nullable lhs, T rhs) { return (lhs.mHasValue) ? lhs.mValue : rhs; } public static TResult? operator??(TOther lhs, Nullable rhs) where TResult = operator TOther ?? T where TResult : struct { if (!rhs.mHasValue) return null; return Nullable(lhs ?? rhs.mValue); } public static TResult? operator??(Nullable lhs, TOther rhs) where TResult = operator T ?? TOther where TResult : struct { if (!lhs.mHasValue) return null; return Nullable(lhs.mValue ?? rhs); } public static TResult? operator??(Nullable lhs, Nullable rhs) where TOther : struct where TResult = operator T ?? TOther where TResult : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return null; return Nullable(lhs.mValue ?? rhs.mValue); } // public static TResult? operator<< (TOther lhs, Nullable rhs) where TResult = operator TOther << T where TResult : struct { if (!rhs.mHasValue) return null; return Nullable(lhs << rhs.mValue); } public static TResult? operator<< (Nullable lhs, TOther rhs) where TResult = operator T << TOther where TResult : struct { if (!lhs.mHasValue) return null; return Nullable(lhs.mValue << rhs); } public static TResult? operator<< (Nullable lhs, Nullable rhs) where TOther : struct where TResult = operator T << TOther where TResult : struct { if ((!lhs.mHasValue) || (!rhs.mHasValue)) return null; return Nullable(lhs.mValue << rhs.mValue); } } extension Nullable : IHashable where T : IHashable { public int GetHashCode() { if (!mHasValue) return 0; return mValue.GetHashCode(); } } }