A type that can contain one or the other type is usually called (not surprisingly) Either . This is a special case such as a sum , mainly a discriminatory union, a labeled union or an incoherent union with exactly two cases (instead of an arbitrary number).
Unfortunately, there are no implementations of the Either type in standard libraries, but there are many implementations that can be found on Google, GitHub and other places ... and porting one of the existing implementations, for example. Haskell or Scala is also not so difficult.
This is a bit like this (forgive my code, I really don't know Cβ―):
using System; abstract class Either<A, B> { public abstract bool IsLeft { get; } public abstract bool IsRight { get; } public abstract A Left { get; } public abstract B Right { get; } public abstract A LeftOrDefault { get; } public abstract B RightOrDefault { get; } public abstract void ForEach(Action<A> action); public abstract void ForEach(Action<B> action); public abstract void ForEach(Action<A> leftAction, Action<B> rightAction); private sealed class L : Either<A, B> { private A Value { get; } public override bool IsLeft => true; public override bool IsRight => false; public override A Left => Value; public override B Right { get { throw new InvalidOperationException(); } } public override A LeftOrDefault => Value; public override B RightOrDefault => default(B); public override void ForEach(Action<A> action) => action(Value); public override void ForEach(Action<B> action) {} public override void ForEach(Action<A> leftAction, Action<B> rightAction) => leftAction(Value); internal L(A value) { Value = value; } } private sealed class R : Either<A, B> { private B Value { get; } public override bool IsLeft => false; public override bool IsRight => true; public override A Left { get { throw new InvalidOperationException(); } } public override B Right => Value; public override A LeftOrDefault => default(A); public override B RightOrDefault => Value; public override void ForEach(Action<A> action) {} public override void ForEach(Action<B> action) => action(Value); public override void ForEach(Action<A> leftAction, Action<B> rightAction) => rightAction(Value); internal R(B value) { Value = value; } } public static Either<A, B> MakeLeft(A value) => new L(value); public static Either<A, B> MakeRight(B value) => new R(value); }
And you will use it as follows:
static class Program { public static void Main() { var input = Console.ReadLine(); int intResult; var result = int.TryParse(input, out intResult) ? Either<int, string>.MakeLeft(intResult) : Either<int, string>.MakeRight(input); result.ForEach(r => Console.WriteLine("You passed me the integer one less than " + ++r), r => Console.WriteLine(r)); } }
source share