Date: October 16, 2019
Original Post: https://gist.github.com/ZacharyPatten/201777593c35b11ea2d90066320113f1
using System;
using System.Linq.Expressions;
using static Towel.Syntax;
namespace Example
{
class Program
{
static void Main(string[] args)
{
// This code contains snippets from the /~https://github.com/ZacharyPatten/Towel project.
// Please check out the project if you want to see more code like it. :)
EnumUnion<A, B> aOrB1 = A.One;
EnumUnion<A, B> aOrB2 = B.One;
Console.WriteLine(aOrB1 == aOrB2);
EnumUnion<A, B> aOrB3 = B.Three;
Console.WriteLine(aOrB1 != aOrB3);
EnumUnion<A, B> aOrB4 = B.NegativeOne;
Console.WriteLine(aOrB4.Value == -1);
}
}
public enum A
{
NegativeOne = -1,
Zero = 0,
One = 1,
}
public enum B
{
NegativeOne = -1,
Zero = 0,
One = 1,
Two = 2,
Three = 3,
}
public struct EnumUnion<A, B>
where A : unmanaged, Enum
where B : unmanaged, Enum
{
public long Value { get; internal set; }
public EnumUnion(A a) => Value = Convert<A, long>(a);
public EnumUnion(B b) => Value = Convert<B, long>(b);
public static implicit operator EnumUnion<A, B>(A a) => new EnumUnion<A, B>(a);
public static implicit operator EnumUnion<A, B>(B b) => new EnumUnion<A, B>(b);
public static bool operator ==(EnumUnion<A, B> a, EnumUnion<A, B> b) => a.Value == b.Value;
public static bool operator !=(EnumUnion<A, B> a, EnumUnion<A, B> b) => a.Value != b.Value;
public static bool operator ==(EnumUnion<A, B> union, A a) => union.Value == Convert<A, long>(a);
public static bool operator !=(EnumUnion<A, B> union, A a) => union.Value != Convert<A, long>(a);
public static bool operator ==(A a, EnumUnion<A, B> union) => union.Value == Convert<A, long>(a);
public static bool operator !=(A a, EnumUnion<A, B> union) => union.Value != Convert<A, long>(a);
public static bool operator ==(EnumUnion<A, B> union, B b) => union.Value == Convert<B, long>(b);
public static bool operator !=(EnumUnion<A, B> union, B b) => union.Value != Convert<B, long>(b);
public static bool operator ==(B b, EnumUnion<A, B> union) => union.Value == Convert<B, long>(b);
public static bool operator !=(B b, EnumUnion<A, B> union) => union.Value != Convert<B, long>(b);
public override int GetHashCode() => Value.GetHashCode();
public override bool Equals(object @object) =>
@object is A a ? a == this :
@object is B b ? b == this :
@object is EnumUnion<A, B> union ? union == this :
false;
}
}
namespace Towel
{
public static class Syntax
{
public static B Convert<A, B>(A a) => ConvertImplementation<A, B>.Function(a);
internal static class ConvertImplementation<A, B>
{
internal static Func<A, B> Function = a =>
{
ParameterExpression A = Expression.Parameter(typeof(A));
Expression BODY = Expression.Convert(A, typeof(B));
Function = Expression.Lambda<Func<A, B>>(BODY, A).Compile();
return Function(a);
};
}
}
}