public static class Extensions
{
public static T Include<T>(this System.Enum type,T value) where T:struct
{
return ((T) (ValueType) (((int) (ValueType) type | (int) (ValueType) value)));
}
public static T Include1<T>(this System.Enum type, T value)
{
return ((T)(object)((int)(object)type | (int)(object)value));
}
}
如果你看到为这两种方法生成的IL它们看起来一样,或者我错过了什么...... 为什么拳击发生在第一个Include方法?
答案 0 :(得分:4)
ValueType
是参考类型。诚实。它只是一个结构T
。您需要将所有ValueType
替换为T
才能将其替换为框。但是,从T
到int
没有内置演员......所以:你不能。你必须装箱。另外,并非所有枚举都以int
为基础(例如,您的box-as-enum,unbox-as-int将因enum Foo : ushort
而失败)。
在C#4.0中,dynamic
可能是一种厚颜无耻的方式:
public static T Include<T>(this T type, T value) where T : struct
{
return ((dynamic)type) | value;
}
否则,一些元编程(基本上是dynamic
做的,但是手动):
static void Main()
{
var both = Test.A.Include(Test.B);
}
enum Test : ulong
{
A = 1, B = 2
}
public static T Include<T>(this T type, T value) where T : struct
{
return DynamicCache<T>.or(type, value);
}
static class DynamicCache<T>
{
public static readonly Func<T, T, T> or;
static DynamicCache()
{
if(!typeof(T).IsEnum) throw new InvalidOperationException(typeof(T).Name + " is not an enum");
var dm = new DynamicMethod(typeof(T).Name + "_or", typeof(T), new Type[] { typeof(T), typeof(T) }, typeof(T),true);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Or);
il.Emit(OpCodes.Ret);
or = (Func<T, T, T>)dm.CreateDelegate(typeof(Func<T, T, T>));
}
}