如何将对整数有效的通用表达式树代码应用于枚举(例如如何使Expression.PostIncrementAssign()对枚举起作用?)? [英] How to apply generic expression-trees code that works well on integers, to enums (e.g. how to make Expression.PostIncrementAssign() work on enums?)?
本文介绍了如何将对整数有效的通用表达式树代码应用于枚举(例如如何使Expression.PostIncrementAssign()对枚举起作用?)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在尝试创建一个扩展方法来做到这一点:
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);
但这不会编译(因为TEnum
是通用的):
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;
}
所以我转向表达式:
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;
}
它适用于整数,但不适用于枚举:行Expression.PostIncrementAssign(fromRefParamExpr)
失败,并带有异常:
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'.'
哪个令人惊讶-enum
不是数字类型吗?我应该做些什么?来回投射enum
⇔int
?
Which is quite suprising - isn't an enum
a numeric type? what am I supposed to do? cast back and forth enum
⇔ int
?
推荐答案
也许这可以为您提供帮助.
maybe this is can help you..
public static IEnumerable<TEnum> RangeToInc<TEnum>(this TEnum from, TEnum to) where
TEnum : struct, IComparable, IFormattable, IConvertible
{
return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Where(
a => a.CompareTo(from) >= 0
&& a.CompareTo(to) <= 0).ToArray(); //Actually it does not need ToArray
}
可扩展性更高
public static IEnumerable<TEnum> RangeToInc<TEnum>(this TEnum from, TEnum to) where
TEnum : struct, IComparable, IFormattable, IConvertible
{
if (typeof(TEnum).IsEnum)
return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Where(
a => a.CompareTo(from) >= 0
&& a.CompareTo(to) <= 0);
else if (typeof(TEnum).IsNumericType())
{
int start = Convert.ToInt32(from);
int count = Convert.ToInt32(to) - start;
return Enumerable.Range(start, count + 1).Cast<TEnum>();
}
throw new NotImplementedException();
}
public static bool IsNumericType(this Type type)
{
switch (Type.GetTypeCode(type))
{
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return true;
default:
return false;
}
}
使用
IEnumerable<DayOfWeek> enumRange = DayOfWeek.Sunday.RangeToInc(DayOfWeek.Wednesday);
foreach (var item in enumRange)
{
Console.Write(item + " ");
//
}
Console.WriteLine();
int a = 4;
var intRange = a.RangeToInc(10);
foreach (var item in intRange)
{
Console.Write(item + " ");
}
//output
// Sunday Monday Tuesday Wednesday
// 4 5 6 7 8 9 10
这篇关于如何将对整数有效的通用表达式树代码应用于枚举(例如如何使Expression.PostIncrementAssign()对枚举起作用?)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文