Enum.TryParse在.NET 3.5的实现 [英] Implementation of Enum.TryParse in .NET 3.5

查看:309
本文介绍了Enum.TryParse在.NET 3.5的实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我怎么能在.NET 3.5实现了.NET 4的Enum.TryParse方法?

公共静态布尔的TryParse< TEnum>(字符串值,出TEnum结果),其中TEnum:结构

解决方案

花费的时间比我希望能得到这个权利,但它的工作原理,并进行了测试。希望这样可以节省别人一些时间!

 私有静态只读的char [] FlagDelimiter =新的[] {','};

    公共静态布尔TryParseEnum< TEnum>(字符串值,出TEnum结果),其中TEnum:结构{
        如果(string.IsNullOrEmpty(值)){
            结果=默认(TEnum);
            返回false;
        }

        VAR enumType = typeof运算(TEnum);

        如果(!enumType.IsEnum)
            抛出新的ArgumentException(的String.Format(类型{0}不是枚举,enumType.FullName));


        结果=默认(TEnum);

        //尝试直接解析值
        如果(Enum.IsDefined(enumType,值)){
            结果=(TEnum)Enum.Parse(enumType,价值);
            返回true;
        }

        //获取在枚举一些信息
        VAR enumValues​​ = Enum.GetValues​​(enumType);
        如果(enumValues​​.Length == 0)
            返回false; //大概不能发生,因为你不能确定空枚举?
        VAR enumType code = Type.GetType code(enumValues​​.GetValue(0).GetType());

        //尝试解析它作为一个标志
        如果(value.IndexOf(,)!=  -  1){
            如果(!Attribute.IsDefined(enumType的typeof(的FlagsAttribute)))
                返回false; //值都有标志,但枚举是不是标志

            // TODO:此缓存效率
            VAR enumInfo =新字典<字符串,对象>();
            VAR enumNames = Enum.GetNames(enumType);
            对于(VAR I = 0; I< enumNames.Length;我++)
                enumInfo.Add(enumNames [I],enumValues​​.GetValue(ⅰ));

            ULONG retVal的= 0;
            的foreach(在value.Split(FlagDelimiter VAR名)){
                变种trimmedName = name.Trim();
                如果(!enumInfo.ContainsKey(trimmedName))
                    返回false; //枚举没有这样的标志

                VAR enumValueObject = enumInfo [trimmedName]
                ULONG enumValueLong;
                开关(enumType code){
                    案件类型code.Byte:
                        enumValueLong =(字节)enumValueObject;
                        打破;
                    案件类型code.SByte:
                        enumValueLong =(字节)((为sbyte)enumValueObject);
                        打破;
                    案件类型code.Int16:
                        enumValueLong =(USHORT)((短)enumValueObject);
                        打破;
                    案件类型code.Int32:
                        enumValueLong =(UINT)((INT)enumValueObject);
                        打破;
                    案件类型code.Int64:
                        enumValueLong =(ULONG)((长)enumValueObject);
                        打破;
                    案件类型code.UInt16:
                        enumValueLong =(USHORT)enumValueObject;
                        打破;
                    案件类型code.UInt32:
                        enumValueLong =(UINT)enumValueObject;
                        打破;
                    案件类型code.UInt64:
                        enumValueLong =(ULONG)enumValueObject;
                        打破;
                    默认:
                        返回false; //应该永远不会发生
                }
                retVal的| = enumValueLong;
            }
            结果=(TEnum)Enum.ToObject(enumType,retVal的);
            返回true;
        }

        //值可以是一个数字,因此,直接分析它
        开关(enumType code){
            案件类型code.SByte:
                为sbyte某人;
                如果(!SByte.TryParse(值,出某人))
                    返回false;
                结果=(TEnum)Enum.ToObject(enumType,某人);
                打破;
            案件类型code.Byte:
                BYTE B;
                如果(!Byte.TryParse(价值,OUT B))
                    返回false;
                结果=(TEnum)Enum.ToObject(enumType,B);
                打破;
            案件类型code.Int16:
                短I16;
                如果(!Int16.TryParse(值,出I16))
                    返回false;
                结果=(TEnum)Enum.ToObject(enumType,I16);
                打破;
            案件类型code.UInt16:
                USHORT U16;
                如果(!UInt16.TryParse(值,从U16))
                    返回false;
                结果=(TEnum)Enum.ToObject(enumType,U16);
                打破;
            案件类型code.Int32:
                INT I32;
                如果(!Int32.TryParse(值,出I32))
                    返回false;
                结果=(TEnum)Enum.ToObject(enumType,I32);
                打破;
            案件类型code.UInt32:
                UINT U32;
                如果(!UInt32.TryParse(值,从U32))
                    返回false;
                结果=(TEnum)Enum.ToObject(enumType,U32);
                打破;
            案件类型code.Int64:
                长I64;
                如果(!Int64.TryParse(值,出I64))
                    返回false;
                结果=(TEnum)Enum.ToObject(enumType,I64);
                打破;
            案件类型code.UInt64:
                ULONG U64;
                如果(!UInt64.TryParse(值,从U64))
                    返回false;
                结果=(TEnum)Enum.ToObject(enumType,U64);
                打破;
            默认:
                返回false; //应该永远不会发生
        }

        返回true;
    }
 

How could I implement the .NET 4's Enum.TryParse method in .NET 3.5?

public static bool TryParse<TEnum>(string value, out TEnum result) where TEnum : struct

解决方案

Took longer than I hoped to get this right, but it works and has been tested. Hope this saves someone some time!

    private static readonly char[] FlagDelimiter = new [] { ',' };

    public static bool TryParseEnum<TEnum>(string value, out TEnum result) where TEnum : struct {
        if (string.IsNullOrEmpty(value)) {
            result = default(TEnum);
            return false;
        }

        var enumType = typeof(TEnum);

        if (!enumType.IsEnum)
            throw new ArgumentException(string.Format("Type '{0}' is not an enum", enumType.FullName));


        result = default(TEnum);

        // Try to parse the value directly 
        if (Enum.IsDefined(enumType, value)) {
            result = (TEnum)Enum.Parse(enumType, value);
            return true;
        }

        // Get some info on enum
        var enumValues = Enum.GetValues(enumType);
        if (enumValues.Length == 0)
            return false;  // probably can't happen as you cant define empty enum?
        var enumTypeCode = Type.GetTypeCode(enumValues.GetValue(0).GetType());

        // Try to parse it as a flag 
        if (value.IndexOf(',') != -1) {
            if (!Attribute.IsDefined(enumType, typeof(FlagsAttribute)))
                return false;  // value has flags but enum is not flags

            // todo: cache this for efficiency
            var enumInfo = new Dictionary<string, object>();
            var enumNames = Enum.GetNames(enumType);
            for (var i = 0; i < enumNames.Length; i++)
                enumInfo.Add(enumNames[i], enumValues.GetValue(i));

            ulong retVal = 0;
            foreach(var name in value.Split(FlagDelimiter)) {
                var trimmedName = name.Trim();
                if (!enumInfo.ContainsKey(trimmedName))
                    return false;   // Enum has no such flag

                var enumValueObject = enumInfo[trimmedName];
                ulong enumValueLong;
                switch (enumTypeCode) {
                    case TypeCode.Byte:
                        enumValueLong = (byte)enumValueObject;
                        break;
                    case TypeCode.SByte:
                        enumValueLong = (byte)((sbyte)enumValueObject);
                        break;
                    case TypeCode.Int16:
                        enumValueLong = (ushort)((short)enumValueObject);
                        break;
                    case TypeCode.Int32:
                        enumValueLong = (uint)((int)enumValueObject);
                        break;
                    case TypeCode.Int64:
                        enumValueLong = (ulong)((long)enumValueObject);
                        break;
                    case TypeCode.UInt16:
                        enumValueLong = (ushort)enumValueObject;
                        break;
                    case TypeCode.UInt32:
                        enumValueLong = (uint)enumValueObject;
                        break;
                    case TypeCode.UInt64:
                        enumValueLong = (ulong)enumValueObject;
                        break;
                    default:
                        return false;   // should never happen
                }
                retVal |= enumValueLong;
            }
            result = (TEnum)Enum.ToObject(enumType, retVal);
            return true;
        }

        // the value may be a number, so parse it directly
        switch (enumTypeCode) {
            case TypeCode.SByte:
                sbyte sb;
                if (!SByte.TryParse(value, out sb))
                    return false;
                result = (TEnum)Enum.ToObject(enumType, sb);
                break;
            case TypeCode.Byte:
                byte b;
                if (!Byte.TryParse(value, out b))
                    return false;
                result = (TEnum)Enum.ToObject(enumType, b);
                break;
            case TypeCode.Int16:
                short i16;
                if (!Int16.TryParse(value, out i16))
                    return false;
                result = (TEnum)Enum.ToObject(enumType, i16);
                break;
            case TypeCode.UInt16:
                ushort u16;
                if (!UInt16.TryParse(value, out u16))
                    return false;
                result = (TEnum)Enum.ToObject(enumType, u16);
                break;
            case TypeCode.Int32:
                int i32;
                if (!Int32.TryParse(value, out i32))
                    return false;
                result = (TEnum)Enum.ToObject(enumType, i32);
                break;
            case TypeCode.UInt32:
                uint u32;
                if (!UInt32.TryParse(value, out u32))
                    return false;
                result = (TEnum)Enum.ToObject(enumType, u32);
                break;
            case TypeCode.Int64:
                long i64;
                if (!Int64.TryParse(value, out i64))
                    return false;
                result = (TEnum)Enum.ToObject(enumType, i64);
                break;
            case TypeCode.UInt64:
                ulong u64;
                if (!UInt64.TryParse(value, out u64))
                    return false;
                result = (TEnum)Enum.ToObject(enumType, u64);
                break;
            default:
                return false; // should never happen
        }

        return true;
    }

这篇关于Enum.TryParse在.NET 3.5的实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆