Только вчера я создал для него решение.В вашем случае enum
s лучше, но вот мое решение для общей неконстантной ситуации переключения.
использования:
static string DigitToStr(int i)
{
return i
.Case(1, "one")
.Case(2, "two")
.Case(3, "three")
.Case(4, "four")
.Case(5, "five")
.Case(6, "six")
.Case(7, "seven")
.Case(8, "eight")
.Case(9, "nine")
.Default("");
}
int a = 1, b = 2, c = 3;
int d = (4 * a * c - b * 2);
string res = true
.Case(d < 0, "No roots")
.Case(d == 0, "One root")
.Case(d > 0, "Two roots")
.Default(_ => { throw new Exception("Impossible!"); });
string res2 = d
.Case(x => x < 0, "No roots")
.Case(x => x == 0, "One root")
.Case(x => x > 0, "Two roots")
.Default(_ => { throw new Exception("Impossible!"); });
string ranges = 11
.Case(1, "one")
.Case(2, "two")
.Case(3, "three")
.Case(x => x >= 4 && x < 10, "small")
.Case(10, "ten")
.Default("big");
определение:
class Res<O, R>
{
public O value;
public bool succ;
public R result;
public Res()
{
}
static public implicit operator R(Res<O, R> v)
{
if (!v.succ)
throw new ArgumentException("No case condition is true and there is no default block");
return v.result;
}
}
static class Op
{
static public Res<O, R> Case<O, V, R>(this Res<O, R> o, V v, R r)
{
if (!o.succ && Equals(o.value, v))
{
o.result = r;
o.succ = true;
}
return o;
}
static public Res<O, R> Case<O, V, R>(this O o, V v, R r)
{
return new Res<O, R>()
{
value = o,
result = r,
succ = Equals(o, v),
};
}
static public Res<O, R> Case<O, R>(this Res<O, R> o, Predicate<O> cond, R r)
{
if (!o.succ && cond(o.value))
{
o.result = r;
o.succ = true;
}
return o;
}
static public Res<O, R> Case<O, R>(this O o, Predicate<O> cond, R r)
{
return new Res<O, R>()
{
value = o,
result = r,
succ = cond(o),
};
}
private static bool Equals<O, V>(O o, V v)
{
return o == null ? v == null : o.Equals(v);
}
static public R Default<O, R>(this Res<O, R> o, R r)
{
return o.succ
? o.result
: r;
}
static public R Default<O, R>(this Res<O, R> o, Func<O, R> def)
{
return o.succ ? o.result : def(o.value);
}
}