3
 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));

    }
}

これら 2 つのメソッドに対して生成された IL が表示される場合、それらは同じように見えるか、何か不足しています...なぜ最初のインクルード メソッドでボックス化が発生しているのでしょうか?

4

1 に答える 1

4

ValueType参照型です。本音。の場合は構造体のみですTValueTypeボックスにしないようにするには、すべてをに置き換える必要がありTます。ただし、組み込みのキャスト from Tto int... はないため、できません。ボックスにする必要があります。さらに、すべての列挙型がintベースであるとは限りません (たとえば、 box-as-enum、unbox-as-int は a に対して失敗し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>));
    }
}
于 2011-06-20T11:44:53.697 に答える