I'm trying to create an extension method to do this:
enum AlphaBet { A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z }
IEnumerable<AlphaBet> rangeCtoG = AlphaBet.C.RangeToInc(AlphaBet.G);
But this won't compile (as TEnum
is generic):
public static IEnumerable<TEnum> RangeToInc<TEnum>(this TEnum from, TEnum to)
where TEnum : struct, IComparable, IFormattable, IConvertible //
{
for (; from <= to; from++)
yield return from;
}
So I turned to expressions:
public delegate void MyFunc<T>(ref T arg); // allow PostIncrementAssign to change the input parameter
public static IEnumerable<TEnum> RangeToInc<TEnum>(this TEnum from, TEnum to)
where TEnum : struct, IComparable, IFormattable, IConvertible //
{
var fromRefParamExpr = Expression.Parameter(typeof(TEnum).MakeByRefType(), "fromParam");
var incrementExpr = Expression.PostIncrementAssign(fromRefParamExpr);
var increment = Expression.Lambda<MyFunc<TEnum>>(incrementExpr, fromRefParamExpr).Compile();
var fromParamExpr = Expression.Parameter(typeof(TEnum), "fromParam");
var toParamExpr = Expression.Parameter(typeof(TEnum), "toParam");
var lessThanOrEqualExpr = Expression.LessThanOrEqual(fromParamExpr, toParamExpr);
var lessThanOrEqual = Expression.Lambda<Func<TEnum, TEnum, bool>>(
lessThanOrEqualExpr, toParamExpr, fromParamExpr).Compile();
for (; lessThanOrEqual(to, from); increment(ref from))
yield return from;
}
It works great with integers, but not with enums: the line Expression.PostIncrementAssign(fromRefParamExpr)
fails with exception:
System.InvalidOperationException:
'The unary operator PostIncrementAssign is not defined for the type
'...+AlphaBet'.'
Which is quite suprising - isn't an enum
a numeric type? what am I supposed to do? cast back and forth enum
⇔ int
?