zoukankan      html  css  js  c++  java
  • 【转载】将C#里的枚举Enum转换为int

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
    本文链接: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();
        }
    }
  • 相关阅读:
    jMeter 里 CSV Data Set Config Sharing Mode 的含义详解
    如何使用 jMeter Parallel Controller
    使用 Chrome 开发者工具 coverage 功能分析 web 应用的渲染阻止资源的执行分布情况
    使用 Chrome 开发者工具的 lighthouse 功能分析 web 应用的性能问题
    关于 SAP 电商云首页加载时触发的 OCC API 请求
    SAP UI5 确保控件 id 全局唯一的实现方法
    SAP 电商云 Accelerator 和 Spartacus UI 的工作机制差异
    介绍一个好用的能让网页变成黑色背景的护眼 Chrome 扩展应用
    Chrome 开发者工具 performance 标签页的用法
    Client Side Cache 和 Server Side Cache 的区别
  • 原文地址:https://www.cnblogs.com/maruko/p/11731681.html
Copyright © 2011-2022 走看看