C# non-boxing conversion of generic enum to int?

前端 未结 9 1798
庸人自扰
庸人自扰 2020-12-04 07:31

Given a generic parameter TEnum which always will be an enum type, is there any way to cast from TEnum to int without boxing/unboxing?

See this example code. This w

相关标签:
9条回答
  • 2020-12-04 08:00

    Here is a simplest and fastest way.
    (with a little restriction. :-) )

    public class BitConvert
    {
        [StructLayout(LayoutKind.Explicit)]
        struct EnumUnion32<T> where T : struct {
            [FieldOffset(0)]
            public T Enum;
    
            [FieldOffset(0)]
            public int Int;
        }
    
        public static int Enum32ToInt<T>(T e) where T : struct {
            var u = default(EnumUnion32<T>);
            u.Enum = e;
            return u.Int;
        }
    
        public static T IntToEnum32<T>(int value) where T : struct {
            var u = default(EnumUnion32<T>);
            u.Int = value;
            return u.Enum;
        }
    }
    

    Restriction:
    This works in Mono. (ex. Unity3D)

    More information about Unity3D:
    ErikE's CastTo class is a really neat way to solve this problem.
    BUT it can't be used as is in Unity3D

    First, it have to be fixed like below.
    (because that the mono compiler can't compile the original code)

    public class CastTo {
        protected static class Cache<TTo, TFrom> {
            public static readonly Func<TFrom, TTo> Caster = Get();
    
            static Func<TFrom, TTo> Get() {
                var p = Expression.Parameter(typeof(TFrom), "from");
                var c = Expression.ConvertChecked(p, typeof(TTo));
                return Expression.Lambda<Func<TFrom, TTo>>(c, p).Compile();
            }
        }
    }
    
    public class ValueCastTo<TTo> : ValueCastTo {
        public static TTo From<TFrom>(TFrom from) {
            return Cache<TTo, TFrom>.Caster(from);
        }
    }
    

    Second, ErikE's code can't be used in AOT platform.
    So, my code is the best solution for Mono.

    To commenter 'Kristof':
    I am sorry that I didn't write all the details.

    0 讨论(0)
  • 2020-12-04 08:04

    I guess you can always use System.Reflection.Emit to create a dynamic method and emit the instructions that do this without boxing, although it might be unverifiable.

    0 讨论(0)
  • 2020-12-04 08:04

    I hope that I'm not too late...

    I think that you should consider to solve your problem with a different approach instead of using Enums try to creating a class with a public static readonly properties.

    if you will use that approach you will have an object that "feels" like an Enum but you will have all the flexibility of a class which means that you can override any of the operators.

    there are other advantages like making that class a partial which will enable you to define the same enum in more then one file/dll which makes it possible to add values to a common dll without recompiling it.

    I couldn't find any good reason not to take that approach (this class will be located in the heap and not on the stack which is slower but it's worth it)

    please let me know what you think.

    0 讨论(0)
提交回复
热议问题