Generate Tagged Union using source generator
- Source distribution, no runtime dependencies
- All unmanaged types will overlap
- All classes will overlap
- Other types are sequential
- Support generics, but generics cannot overlap
[Union]
public readonly partial struct Union1
{
// This template is not used at runtime, its only purpose is to provide type symbols to the roslyn analyzer
[UnionTemplate]
private interface Template
{
int A();
string B();
bool C();
(int a, int b) D();
void E(); // Tag only variant
List<int>? F();
(int a, string b) G();
// Record mode, in this mode, multiple fields are stored separately.
void H(int a, int b, string c, HashSet<int> d, (int a, string b) e);
}
}
Will generate (pseudocode):
public readonly partial struct Union1
{
private readonly __impl_ _impl;
// If the first item is a Tag only, it starts at 0, otherwise it starts at 1
// Use [UnionTag(value)] to explicitly mark enum values
public enum Tags : byte { A = 1, B, C, D, E, F, G, H }
private struct __impl_
{
public object? _c0; // All classes will overlap
public object? _c1;
public __unmanaged_ _u; // All unmanaged types will overlap
public (int a, string b) _f0_0; // Mixed types cannot overlap
public readonly Tags _tag;
[StructLayout(LayoutKind.Explicit)] internal struct __unmanaged_
{
[FieldOffset(0)] public int _0;
[FieldOffset(0)] public bool _1;
[FieldOffset(0)] public (int a, int b) _2;
[FieldOffset(0)] public __record_7_unmanaged_ _3;
}
// The fields of the record mode variant are stored separately, with the unmanaged part having a separate structure
internal struct __record_7_unmanaged_
{
public int _0;
public int _1;
}
}
public static Union1 MakeA(int value) { ... }
public static Union1 MakeB(string value) { ... }
public static Union1 MakeC(bool value) { ... }
public static Union1 MakeD((int a, int b) value) { ... }
public static Union1 MakeE() { ... }
public static Union1 MakeF(List<int>? value) { ... }
public static Union1 MakeG((int a, string b) value) { ... }
public static Union1 MakeH(int a, int b, string c, HashSet<int> d, (int a, string b) e) { ... }
public readonly Tags Tag { get; }
public readonly bool IsA { get; }
public readonly bool IsB { get; }
public readonly bool IsC { get; }
public readonly bool IsD { get; }
public readonly bool IsE { get; }
public readonly bool IsF { get; }
public readonly bool IsG { get; }
public readonly bool IsH { get; }
// ref readonly if sturct is readonly, otherwise ref only
// If the current tag does not match, a null reference will be returned
public ref readonly int A { get; }
public ref readonly string B { get; }
public ref readonly bool C { get; }
public ref readonly (int a, int b) D { get; }
// E is a Tag only so there is no value getter
public ref readonly List<int>? F { get; }
public ref readonly (int a, string b) G { get; }
// Record mode will get a magic view struct which has some getters to calculate the field references
public ref readonly VariantHView H => ref Unsafe.As<__impl_, VariantHView>(ref _impl);
... Eq Cmp ToString
// The magic struct, that can use the this reference to compute the actual field reference by reinterpreting __impl_ as this struct
public struct VariantHView
{
private readonly __impl_ _impl;
public ref readonly int a { get; }
public ref readonly int b { get; }
public ref readonly string c { get; }
public ref readonly HashSet<int> d { get; }
public ref readonly (int a, string b) e { get; }
...
}
}
Complete generate output:
Union1.union.g.cs
// <auto-generated/>
#nullable disable warnings
#nullable enable annotations
using Coplt.Union;
public readonly partial struct Union1
: global::Coplt.Union.ITaggedUnion
, global::System.IEquatable<Union1>
, global::System.IComparable<Union1>
#if NET7_0_OR_GREATER
, global::System.Numerics.IEqualityOperators<Union1, Union1, bool>
, global::System.Numerics.IComparisonOperators<Union1, Union1, bool>
#endif
{
private readonly __impl_ _impl;
private Union1(__impl_ _impl) { this._impl = _impl; }
public readonly Tags Tag
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => this._impl._tag;
}
public enum Tags : byte
{
A = 1,
B,
C,
D,
E,
F,
G,
H,
}
[global::System.Runtime.CompilerServices.CompilerGenerated]
[global::System.Runtime.InteropServices.StructLayout(global::System.Runtime.InteropServices.LayoutKind.Auto)]
internal struct __impl_
{
public object? _c0;
public object? _c1;
public __unmanaged_ _u;
public (int a, string b) _f0_0;
public readonly Tags _tag;
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public __impl_(Tags _tag)
{
this._c0 = null;
this._c1 = null;
global::System.Runtime.CompilerServices.Unsafe.SkipInit(out this._u);
this._f0_0 = default!;
this._tag = _tag;
}
[global::System.Runtime.CompilerServices.CompilerGenerated]
[global::System.Runtime.InteropServices.StructLayout(global::System.Runtime.InteropServices.LayoutKind.Explicit)]
internal struct __unmanaged_
{
[global::System.Runtime.InteropServices.FieldOffset(0)]
public int _0;
[global::System.Runtime.InteropServices.FieldOffset(0)]
public bool _1;
[global::System.Runtime.InteropServices.FieldOffset(0)]
public (int a, int b) _2;
[global::System.Runtime.InteropServices.FieldOffset(0)]
public __record_7_unmanaged_ _3;
}
[global::System.Runtime.CompilerServices.CompilerGenerated]
[global::System.Runtime.InteropServices.StructLayout(global::System.Runtime.InteropServices.LayoutKind.Auto)]
internal struct __record_7_unmanaged_
{
public int _0;
public int _1;
}
}
public partial record struct VariantH(int a, int b, string c, global::System.Collections.Generic.HashSet<int> d, (int a, string b) e);
public readonly struct VariantHView :
global::System.IEquatable<VariantHView>
, global::System.IComparable<VariantHView>
#if NET7_0_OR_GREATER
, global::System.Numerics.IEqualityOperators<VariantHView, VariantHView, bool>
, global::System.Numerics.IComparisonOperators<VariantHView, VariantHView, bool>
#endif
{
private readonly __impl_ _impl;
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public VariantHView()
{
_impl = new __impl_(Tags.H);
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly int a
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref global::System.Runtime.CompilerServices.Unsafe.AsRef<Union1.__impl_>(in this._impl)._u._3._0;
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly int b
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref global::System.Runtime.CompilerServices.Unsafe.AsRef<Union1.__impl_>(in this._impl)._u._3._1;
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly string c
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref global::System.Runtime.CompilerServices.Unsafe.As<object?, string>(ref global::System.Runtime.CompilerServices.Unsafe.AsRef<Union1.__impl_>(in this._impl)._c0);
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly global::System.Collections.Generic.HashSet<int> d
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref global::System.Runtime.CompilerServices.Unsafe.As<object?, global::System.Collections.Generic.HashSet<int>>(ref global::System.Runtime.CompilerServices.Unsafe.AsRef<Union1.__impl_>(in this._impl)._c1);
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly (int a, string b) e
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref global::System.Runtime.CompilerServices.Unsafe.AsRef<Union1.__impl_>(in this._impl)._f0_0;
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public bool Equals(VariantHView other) =>
global::System.Collections.Generic.EqualityComparer<int>.Default.Equals(a, other.a) &&
global::System.Collections.Generic.EqualityComparer<int>.Default.Equals(b, other.b) &&
global::System.Collections.Generic.EqualityComparer<string>.Default.Equals(c, other.c) &&
global::System.Collections.Generic.EqualityComparer<global::System.Collections.Generic.HashSet<int>>.Default.Equals(d, other.d) &&
global::System.Collections.Generic.EqualityComparer<(int a, string b)>.Default.Equals(e, other.e);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() => global::System.HashCode.Combine(a, b, c, d, e);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public override bool Equals(object? obj) => obj is VariantHView other && Equals(other);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator ==(VariantHView left, VariantHView right) => Equals(left, right);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator !=(VariantHView left, VariantHView right) => !Equals(left, right);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public int CompareTo(VariantHView other)
{
var _0 = global::System.Collections.Generic.Comparer<int>.Default.Compare(a, other.a);
if (_0 != 0) return _0;
var _1 = global::System.Collections.Generic.Comparer<int>.Default.Compare(b, other.b);
if (_1 != 0) return _1;
var _2 = global::System.Collections.Generic.Comparer<string>.Default.Compare(c, other.c);
if (_2 != 0) return _2;
var _3 = global::System.Collections.Generic.Comparer<global::System.Collections.Generic.HashSet<int>>.Default.Compare(d, other.d);
if (_3 != 0) return _3;
var _4 = global::System.Collections.Generic.Comparer<(int a, string b)>.Default.Compare(e, other.e);
if (_4 != 0) return _4;
return 0;
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator <(VariantHView left, VariantHView right) => left.CompareTo(right) < 0;
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator >(VariantHView left, VariantHView right) => left.CompareTo(right) > 0;
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator <=(VariantHView left, VariantHView right) => left.CompareTo(right) <= 0;
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator >=(VariantHView left, VariantHView right) => left.CompareTo(right) >= 0;
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public override string ToString() => $"{nameof(Union1)}.{nameof(Tags.H)} {{ a = {a}, b = {b}, c = {c}, d = {d}, e = {e} }}";
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static implicit operator VariantH(VariantHView v) => new VariantH(v.a, v.b, v.c, v.d, v.e);
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static Union1 MakeA(int value)
{
var _impl = new __impl_(Tags.A);
_impl._u._0 = value;
return new Union1(_impl);
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static Union1 MakeB(string value)
{
var _impl = new __impl_(Tags.B);
_impl._c0 = value;
return new Union1(_impl);
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static Union1 MakeC(bool value)
{
var _impl = new __impl_(Tags.C);
_impl._u._1 = value;
return new Union1(_impl);
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static Union1 MakeD((int a, int b) value)
{
var _impl = new __impl_(Tags.D);
_impl._u._2 = value;
return new Union1(_impl);
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static Union1 MakeE()
{
var _impl = new __impl_(Tags.E);
return new Union1(_impl);
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static Union1 MakeF(global::System.Collections.Generic.List<int>? value)
{
var _impl = new __impl_(Tags.F);
_impl._c0 = value;
return new Union1(_impl);
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static Union1 MakeG((int a, string b) value)
{
var _impl = new __impl_(Tags.G);
_impl._f0_0 = value;
return new Union1(_impl);
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static Union1 MakeH(int a, int b, string c, global::System.Collections.Generic.HashSet<int> d, (int a, string b) e)
{
var _impl = new __impl_(Tags.H);
_impl._u._3._0 = a;
_impl._u._3._1 = b;
_impl._c0 = c;
_impl._c1 = d;
_impl._f0_0 = e;
return new Union1(_impl);
}
public readonly bool IsA
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => this._impl._tag == Tags.A;
}
public readonly bool IsB
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => this._impl._tag == Tags.B;
}
public readonly bool IsC
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => this._impl._tag == Tags.C;
}
public readonly bool IsD
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => this._impl._tag == Tags.D;
}
public readonly bool IsE
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => this._impl._tag == Tags.E;
}
public readonly bool IsF
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => this._impl._tag == Tags.F;
}
public readonly bool IsG
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => this._impl._tag == Tags.G;
}
public readonly bool IsH
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => this._impl._tag == Tags.H;
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly int A
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref !this.IsA ? ref global::System.Runtime.CompilerServices.Unsafe.NullRef<int>() : ref this._impl._u._0!;
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly string B
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref !this.IsB ? ref global::System.Runtime.CompilerServices.Unsafe.NullRef<string>() : ref global::System.Runtime.CompilerServices.Unsafe.As<object?, string>(ref global::System.Runtime.CompilerServices.Unsafe.AsRef<Union1.__impl_>(in this._impl)._c0);
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly bool C
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref !this.IsC ? ref global::System.Runtime.CompilerServices.Unsafe.NullRef<bool>() : ref this._impl._u._1!;
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly (int a, int b) D
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref !this.IsD ? ref global::System.Runtime.CompilerServices.Unsafe.NullRef<(int a, int b)>() : ref this._impl._u._2!;
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly global::System.Collections.Generic.List<int>? F
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref !this.IsF ? ref global::System.Runtime.CompilerServices.Unsafe.NullRef<global::System.Collections.Generic.List<int>?>() : ref global::System.Runtime.CompilerServices.Unsafe.As<object?, global::System.Collections.Generic.List<int>?>(ref global::System.Runtime.CompilerServices.Unsafe.AsRef<Union1.__impl_>(in this._impl)._c0);
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly (int a, string b) G
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref !this.IsG ? ref global::System.Runtime.CompilerServices.Unsafe.NullRef<(int a, string b)>() : ref this._impl._f0_0!;
}
[global::System.Diagnostics.CodeAnalysis.UnscopedRef]
public ref readonly VariantHView H
{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
get => ref !this.IsH ? ref global::System.Runtime.CompilerServices.Unsafe.NullRef<VariantHView>() : ref global::System.Runtime.CompilerServices.Unsafe.As<__impl_, VariantHView>(ref global::System.Runtime.CompilerServices.Unsafe.AsRef<Union1.__impl_>(in this._impl));
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public readonly bool Equals(Union1 other) => this.Tag != other.Tag ? false : this.Tag switch
{
Tags.A => global::System.Collections.Generic.EqualityComparer<int>.Default.Equals(this.A, other.A),
Tags.B => global::System.Collections.Generic.EqualityComparer<string>.Default.Equals(this.B, other.B),
Tags.C => global::System.Collections.Generic.EqualityComparer<bool>.Default.Equals(this.C, other.C),
Tags.D => global::System.Collections.Generic.EqualityComparer<(int a, int b)>.Default.Equals(this.D, other.D),
Tags.F => global::System.Collections.Generic.EqualityComparer<global::System.Collections.Generic.List<int>?>.Default.Equals(this.F, other.F),
Tags.G => global::System.Collections.Generic.EqualityComparer<(int a, string b)>.Default.Equals(this.G, other.G),
Tags.H => this.H.Equals(other.H),
_ => true,
};
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public readonly override int GetHashCode() => this.Tag switch
{
Tags.A => global::System.HashCode.Combine(this.Tag, this.A),
Tags.B => global::System.HashCode.Combine(this.Tag, this.B),
Tags.C => global::System.HashCode.Combine(this.Tag, this.C),
Tags.D => global::System.HashCode.Combine(this.Tag, this.D),
Tags.F => global::System.HashCode.Combine(this.Tag, this.F),
Tags.G => global::System.HashCode.Combine(this.Tag, this.G),
Tags.H => global::System.HashCode.Combine(this.Tag, this.H),
_ => global::System.HashCode.Combine(this.Tag),
};
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public readonly override bool Equals(object? obj) => obj is Union1 other && Equals(other);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Union1 left, Union1 right) => Equals(left, right);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Union1 left, Union1 right) => !Equals(left, right);
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public readonly int CompareTo(Union1 other) => this.Tag != other.Tag ? global::System.Collections.Generic.Comparer<Tags>.Default.Compare(this.Tag, other.Tag) : this.Tag switch
{
Tags.A => global::System.Collections.Generic.Comparer<int>.Default.Compare(this.A, other.A),
Tags.B => global::System.Collections.Generic.Comparer<string>.Default.Compare(this.B, other.B),
Tags.C => global::System.Collections.Generic.Comparer<bool>.Default.Compare(this.C, other.C),
Tags.D => global::System.Collections.Generic.Comparer<(int a, int b)>.Default.Compare(this.D, other.D),
Tags.F => global::System.Collections.Generic.Comparer<global::System.Collections.Generic.List<int>?>.Default.Compare(this.F, other.F),
Tags.G => global::System.Collections.Generic.Comparer<(int a, string b)>.Default.Compare(this.G, other.G),
Tags.H => this.H.CompareTo(other.H),
_ => 0,
};
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator <(Union1 left, Union1 right) => left.CompareTo(right) < 0;
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator >(Union1 left, Union1 right) => left.CompareTo(right) > 0;
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator <=(Union1 left, Union1 right) => left.CompareTo(right) <= 0;
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static bool operator >=(Union1 left, Union1 right) => left.CompareTo(right) >= 0;
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public readonly override string ToString() => this.Tag switch
{
Tags.A => $"{nameof(Union1)}.{nameof(Tags.A)} {{ {(this.A)} }}",
Tags.B => $"{nameof(Union1)}.{nameof(Tags.B)} {{ {(this.B)} }}",
Tags.C => $"{nameof(Union1)}.{nameof(Tags.C)} {{ {(this.C)} }}",
Tags.D => $"{nameof(Union1)}.{nameof(Tags.D)} {{ {(this.D)} }}",
Tags.E => $"{nameof(Union1)}.{nameof(Tags.E)}",
Tags.F => $"{nameof(Union1)}.{nameof(Tags.F)} {{ {(this.F)} }}",
Tags.G => $"{nameof(Union1)}.{nameof(Tags.G)} {{ {(this.G)} }}",
Tags.H => $"{(this.H)}",
_ => nameof(Union1),
};
}
You can manually determine the Tag or use pattern matching.
But remember C# does not have enum exhaustion semantics.
var u = Union1.MakeA(123);
if (u is { Tag: Union1.Tags.A, A: var a }) { }
if (u is { IsA: true, A: var a }) { }
if (u.IsA)
{
var a = u.A;
}
switch (u.Tag)
{
case Union1.Tags.A:
break;
...
}
switch (u.Tag)
{
case { IsA: true, A: var a }:
break;
...
}