带有标志属性的 Enum.TryParse
Posted
技术标签:
【中文标题】带有标志属性的 Enum.TryParse【英文标题】:Enum.TryParse with Flags attribute 【发布时间】: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
谢谢!
【问题讨论】:
【参考方案1】:从 .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 块?【参考方案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】:@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 不会有什么不同,除非我遗漏了什么,除了因为约束在结构上,我认为我们需要检查调用是否在有效枚举上在检查值是否为空之前输入以上是关于带有标志属性的 Enum.TryParse的主要内容,如果未能解决你的问题,请参考以下文章