OneOf.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. namespace MeloongCore;
  2. public readonly struct OneOf<T0, T1> {
  3. private readonly int _index = -1; // -1 表示未初始化(这是一个 struct,所以这可以让默认值不为 0)
  4. private readonly T0? _value0;
  5. private readonly T1? _value1;
  6. public static implicit operator OneOf<T0, T1>(T0 value) => new(0, value, default);
  7. public static implicit operator OneOf<T0, T1>(T1 value) => new(1, default, value);
  8. public static implicit operator T0(OneOf<T0, T1> value) => value.As<T0>();
  9. public static implicit operator T1(OneOf<T0, T1> value) => value.As<T1>();
  10. private OneOf(int index, T0? value0, T1? value1) {
  11. _index = index;
  12. _value0 = value0;
  13. _value1 = value1;
  14. }
  15. /// <summary>
  16. /// 对不同类型执行不同的操作,并返回同一个值。
  17. /// </summary>
  18. public TResult Switch<TResult>(Func<T0, TResult> f0, Func<T1, TResult> f1) => _index switch {
  19. 0 => f0(_value0!),
  20. 1 => f1(_value1!),
  21. _ => throw new InvalidOperationException()
  22. };
  23. /// <summary>
  24. /// 对不同类型执行不同的操作。
  25. /// </summary>
  26. public void Switch(Action<T0> f0, Action<T1> f1) {
  27. if (_index == 0) f0(_value0!);
  28. else if (_index == 1) f1(_value1!);
  29. else throw new InvalidOperationException();
  30. }
  31. /// <summary>
  32. /// 判断当前的类型是否为 T。
  33. /// </summary>
  34. public bool Is<T>() => _index switch {
  35. 0 when typeof(T) == typeof(T0) => true,
  36. 1 when typeof(T) == typeof(T1) => true,
  37. _ => false
  38. };
  39. /// <summary>
  40. /// 假定当前的类型为 T,并返回该值。
  41. /// 若当前值的类型不为 T,则抛出 <see cref="InvalidOperationException"/>。
  42. /// </summary>
  43. public T As<T>() => _index switch {
  44. 0 when typeof(T) == typeof(T0) => (T)(object)_value0!,
  45. 1 when typeof(T) == typeof(T1) => (T)(object)_value1!,
  46. _ => throw new InvalidOperationException()
  47. };
  48. }
  49. public readonly struct OneOf<T0, T1, T2> {
  50. private readonly int _index = -1; // -1 表示未初始化(这是一个 struct,所以这可以让默认值不为 0)
  51. private readonly T0? _value0;
  52. private readonly T1? _value1;
  53. private readonly T2? _value2;
  54. public static implicit operator OneOf<T0, T1, T2>(T0 value) => new(0, value, default, default);
  55. public static implicit operator OneOf<T0, T1, T2>(T1 value) => new(1, default, value, default);
  56. public static implicit operator OneOf<T0, T1, T2>(T2 value) => new(2, default, default, value);
  57. public static implicit operator T0(OneOf<T0, T1, T2> value) => value.As<T0>();
  58. public static implicit operator T1(OneOf<T0, T1, T2> value) => value.As<T1>();
  59. public static implicit operator T2(OneOf<T0, T1, T2> value) => value.As<T2>();
  60. private OneOf(int index, T0? value0, T1? value1, T2? value2) {
  61. _index = index;
  62. _value0 = value0;
  63. _value1 = value1;
  64. _value2 = value2;
  65. }
  66. /// <summary>
  67. /// 对不同类型执行不同的操作,并返回同一个值。
  68. /// </summary>
  69. public TResult Switch<TResult>(Func<T0, TResult> f0, Func<T1, TResult> f1, Func<T2, TResult> f2) => _index switch {
  70. 0 => f0(_value0!),
  71. 1 => f1(_value1!),
  72. 2 => f2(_value2!),
  73. _ => throw new InvalidOperationException()
  74. };
  75. /// <summary>
  76. /// 对不同类型执行不同的操作。
  77. /// </summary>
  78. public void Switch(Action<T0> f0, Action<T1> f1, Action<T2> f2) {
  79. if (_index == 0) f0(_value0!);
  80. else if (_index == 1) f1(_value1!);
  81. else if (_index == 2) f2(_value2!);
  82. else throw new InvalidOperationException();
  83. }
  84. /// <summary>
  85. /// 判断当前的类型是否为 T。
  86. /// </summary>
  87. public bool Is<T>() => _index switch {
  88. 0 when typeof(T) == typeof(T0) => true,
  89. 1 when typeof(T) == typeof(T1) => true,
  90. 2 when typeof(T) == typeof(T2) => true,
  91. _ => false
  92. };
  93. /// <summary>
  94. /// 假定当前的类型为 T,并返回该值。
  95. /// 若当前值的类型不为 T,则抛出 <see cref="InvalidOperationException"/>。
  96. /// </summary>
  97. public T As<T>() => _index switch {
  98. 0 when typeof(T) == typeof(T0) => (T) (object) _value0!,
  99. 1 when typeof(T) == typeof(T1) => (T) (object) _value1!,
  100. 2 when typeof(T) == typeof(T2) => (T) (object) _value2!,
  101. _ => throw new InvalidOperationException()
  102. };
  103. }