【问题标题】:Enum.TryParse with Flags attribute带有标志属性的 Enum.TryParse
【发布时间】:2011-02-14 06:39:00
【问题描述】:

我已经按值或按名称将代码写入TryParse 枚举,如下所示。如何扩展此代码以包含解析具有 Flags 属性的枚举?

    public static bool TryParse<T>(this T enum_type, object value, out T result) 
                where T : struct
            {
                return enum_type.TryParse<T>(value, true, out result);
            }



 public static bool TryParse<T>(this T enum_type, 
object value, bool ignoreCase, out T result)
        where T : struct
    {
        result = default(T);
        var is_converted = false;

        var is_valid_value_for_conversion = new Func<T, object, bool, bool>[]{
            (e, v, i) => e.GetType().IsEnum,
            (e, v, i) => v != null,
            (e, v, i) => Enum.GetNames(e.GetType()).Any(n => String.Compare(n, v.ToString(), i) == 0) || Enum.IsDefined(e.GetType(), v)
        };

        if(is_valid_value_for_conversion.All(rule => rule(enum_type, value, ignoreCase))){
            result = (T)Enum.Parse(typeof(T), value.ToString(), ignoreCase);
            is_converted = true;
        }

        return is_converted;
    }

目前此代码适用于以下枚举:

enum SomeEnum{ A, B, C } 
// can parse either by 'A' or 'a'

enum SomeEnum1 : int { A = 1, B = 2, C = 3 } 
// can parse either by 'A' or 'a' or 1 or "1"

不适用于:

[Flags]
enum SomeEnum2 { A = 1, B = 2, C = 4 } // can parse either by 'A' or 'a'
// cannot parse for A|B

谢谢!

【问题讨论】:

    标签: .net json.net .net-3.5


    【解决方案1】:

    @Pop 的回答给了我一个线索,我修改了代码中的规则检查,如下所示:

    var is_valid_value_for_conversion = new Func<T, object, bool, bool>[]
    {
        (e, v, i) => e.GetType().IsEnum,
        (e, v, i) => value != null,
        (e, v, i) => Enum.GetNames(e.GetType()).Any(
                    n => String.Compare(n, v.ToString(), i) == 0 
                    || (v.ToString().Contains(",") && v.ToString().ToLower().Contains(n.ToLower()))) 
                    || Enum.IsDefined(e.GetType(), v)
    };
    

    其余部分保持不变,对我有用

    其他人

    【讨论】:

    • 空检查不应该是你的第一条规则吗?
    • 第一次检查或第二次检查在这种情况下 IMO 不会有什么不同,除非我遗漏了什么,除了因为约束在结构上,我认为我们需要检查调用是否在有效枚举上在检查值是否为空之前输入
    【解决方案2】:

    标志枚举是使用, 通过使用.Net 约定而不是| 编写的。 Enum.Parse() 在使用 ',' 字符串时完美运行:

    [Flags]
    public enum Flags
    {
        A = 1,
        B = 2,
        C = 4,
        D = 8,
    }
    
    var enumString =  (Flags.A | Flags.B | Flags.C).ToString();
    Console.WriteLine(enumString); // Outputs: A, B, C
    Flags f = (Flags)Enum.Parse(typeof(Flags),  enumString);
    Console.WriteLine(f); // Outputs: A, B, C
    

    【讨论】:

      【解决方案3】:

      从 .NET 4 开始,有一个 Enum.TryParse<T> 方法。它支持 Flags 开箱即用的枚举:

      string x = (SomeEnum2.A | SomeEnum2.B).ToString();  //  x == "A, B"
      SomeEnum2 y;
      bool success = Enum.TryParse<SomeEnum2>(x, out y);  //  y == A|B
      

      【讨论】:

      • 为什么不直接使用 Enum.Parse 并在其周围包裹一个 try/catch 块?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多