将C#里的枚举Enum转换为int

将C#里的枚举Enum转换为int

https://blog.csdn.net/lzdidiv/article/details/71170528

 

将枚举类型转换为int在C#里非常简单,直接(int)强转就行了,可是这样写代码不方便,尤其让我这种懒癌患者难受,我喜欢用扩展方法的方式实现转换(如果不理解扩展方法请自行补课,这里不再介绍),比如这样string转int:

    public static class ExtendString
    {
        public static int ToInt(this string s, int defaultValue = 0)
        {
            int i;
            return int.TryParse(s, out i) ? i : defaultValue;
        }
    }

比什么Convert或者Parse不知道高到哪里去了:

    string str = "123";
    int i = str.ToInt();

同样处理Enum行不行?

    public static class ExtendEnum
    {
        public static int ToInt(this System.Enum e)
        {
            return (int)e;
        }
    }

很可惜Enum类型的实参可以强转为int,但是形参不行,编译器提示无法转换类型,非常令人无语。

不过用个object做中介就能强转了:

    public static int ToInt(this System.Enum e)
    {
        return (int)(object)e;
    }

这时我们的枚举变量都可以调用ToInt()了,貌似一切都成功了。

身为本文作者的我敏锐的发现这种做法有个致命缺陷——装箱,它是代码性能骤降的一大元凶,我们要尽力避免它的存在。

先尝试改动转换方法:

    public static int ToInt(this System.Enum e)
    {
        return System.Convert.ToInt32(e);
    }

结果发现e是以object类型被传参的,跟前一种做法相比没有本质区别。

思考良久我突然灵光一闪:任何对象都有 GetHashCode() 方法,用于返回该对象数据的Hash值,C#的常见内部类型都各自重载了该方法,比如int对象返回的Hash值就是它的数值本身,同为整型数据的Enum应该也返回它的数值才对。

为了防止搞出乌龙,那就查一下Enum类的源码吧,下面我把GetHashCode()的源码贴出来:

    [System.Security.SecuritySafeCritical]
    public override unsafe int GetHashCode()
    {
        // Avoid boxing by inlining GetValue()
        // return GetValue().GetHashCode();
     
        fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data)
        {
            switch (InternalGetCorElementType())
            {
                case CorElementType.I1:
                    return (*(sbyte*)pValue).GetHashCode();
                case CorElementType.U1:
                    return (*(byte*)pValue).GetHashCode();
                case CorElementType.Boolean:
                    return (*(bool*)pValue).GetHashCode();
                case CorElementType.I2:
                    return (*(short*)pValue).GetHashCode();
                case CorElementType.U2:
                    return (*(ushort*)pValue).GetHashCode();
                case CorElementType.Char:
                    return (*(char*)pValue).GetHashCode();
                case CorElementType.I4:
                    return (*(int*)pValue).GetHashCode();
                case CorElementType.U4:
                    return (*(uint*)pValue).GetHashCode();
                case CorElementType.R4:
                    return (*(float*)pValue).GetHashCode();
                case CorElementType.I8:
                    return (*(long*)pValue).GetHashCode();
                case CorElementType.U8:
                    return (*(ulong*)pValue).GetHashCode();
                case CorElementType.R8:
                    return (*(double*)pValue).GetHashCode();
                case CorElementType.I:
                    return (*(IntPtr*)pValue).GetHashCode();
                case CorElementType.U:
                    return (*(UIntPtr*)pValue).GetHashCode();
                default:
                    Contract.Assert(false, "Invalid primitive type");
                    return 0;
            }
        }
    }

果然是强转为int后再GetHashCode(),等价于强转int

再看看最顶上的注释,我跟微软英雄所见略同啊哈哈

所以最后得到的代码为:

    public static class ExtendEnum
    {
        public static int ToInt(this System.Enum e)
        {
            return e.GetHashCode();
        }
    }
————————————————
版权声明:本文为CSDN博主「九德真君」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lzdidiv/article/details/71170528

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值