我知道这是一个老问题,但我今天遇到了这个问题,我想扩展Josh Comley的答案(https://stackoverflow.com/a/23177585/3403999)
Josh的回答中有几个错误的假设,我想指出:
It assumes that the '-' is always the negative sign. I don't know if there is any cultures that use a different sign, but .Net certainly allows for it in the NumberFormatInfo (https://learn.microsoft.com/en-us/dotnet/api/system.globalization.numberformatinfo.negativesign?view=net-5.0). About the only one I can think of that might be common is the parenthesis, ie (1) == -1.
Enum members have to start with an alphabetic character. Specifically, I know you can use an underscore as the first char. IE, enum MyEnum { _One = 1 } is valid.
Not really sure this exactly wrong, but it made the assumption that anything outside the range of '0' to '9' and '-' is a valid alphabetic character. It seemed like a bad assumption cause there are control characters outside that range that would return true - albeit, I don't think you can get those control characters into an enum member name without it throwing a compile error.
总之,这是我的最新解决方案:
public static bool IsValid<TEnum>(this TEnum value) where TEnum : System.Enum
{
char first = value.ToString()[0];
return (char.IsLetter(first) || first == '_');
}
我发现可以在枚举成员名中使用来自其他语言的Unicode字母(https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/identifier-names)。在这方面,我的解决办法仍然可行。我使用以下enum进行测试:enum MyEnum {\u05D0}。已编译的枚举,IsValid返回true。
我很好奇,与使用带有枚举值(enumenumvalues (typeof(TEnum))填充的HashSet的静态helper类相比,走这条路会带来什么样的性能打击,其中您可以检查HashSet是否包含enum值。这个想法是两个Enum。GetValues和Enum。IsDefined只是对昂贵的反射命中的包装,所以你用GetValues做一次反射,缓存结果,然后只检查HashSet。
我使用StopWatch和Random运行了一个相当简单的测试,它将生成有效和无效的enum值,然后我通过3个不同的方法运行它们:ToString方法、GetValues HashSet方法和IsDefined方法。每个方法都是int。执行时间。结果:
当我运行20亿次时,ToString平均每次大约2分钟。
GetValues HashSet每次运行20亿次大约50秒。
每次运行20亿次,IsDefined大约5分钟。
因此,如果性能是一个问题,或者您正在进行循环,那么推荐IsDefined的所有解决方案可能都不是一个好主意。如果您只是在单个实例上使用它来验证用户输入,那么这可能无关紧要。
对于HashSet,对于运行它的每个不同枚举,性能都会受到较小的影响(因为第一次运行一个新的枚举类型会生成一个新的静态HashSet)。不科学,但似乎我的PC上的盈亏平衡点是单个枚举运行大约200k到300k次,然后才开始使用ToString方法执行。
ToString方法虽然不是最快的,但它在处理IsDefined和HashSet都不能容纳的Flags枚举方面有额外的好处。
如果性能确实是一个问题,不要使用这3种方法中的任何一种。相反,编写一个方法来验证针对该枚举优化的特定枚举。
还要注意,我的测试使用的是相对较小的枚举(大约5个元素)。我不知道当你开始使用更大的枚举时,ToString和HashSet之间的性能如何。