解析枚举的困惑

我正在将字符串类型的数值转换为相应的枚举。 当我测试我的代码时,我发现有趣的行为令我感到困惑。

使用下面的代码示例,如果/当“s”变量的值与Enum值之一不匹配时,有人可以阐明为什么不抛出exception? 另外,如何将sEnum var设置为Stooge枚举定义中不存在的值?

class Program { enum Stooge { Unspecified, Moe, Larry, Curly, Shemp } static void Main(string[] args) { while (true) { Console.WriteLine("Enter a number..."); string s = Console.ReadLine(); Stooge sEnum = (Stooge)(int.Parse(s)); //Why doesn't this line throw if s != 0, 1, 2, 3, or 4? Console.WriteLine("\r\nYou entered: {0}\r\nEnum String Value: {1}\r\nEnum Int Value: {2}\r\n", s, sEnum.ToString(), (int)sEnum); } } } 

这是创建.NET的人的决定。 枚举由另一个值类型( intshortbyte等)支持,因此它实际上可以具有对这些值类型有效的任何值。

我个人并不喜欢它的工作方式,因此我制作了一系列实用方法:

 ///  /// Utility methods for enum values. This static type will fail to initialize /// (throwing a ) if /// you try to provide a value that is not an enum. ///  /// An enum type.  public static class EnumUtil where T : struct, IConvertible // Try to get as much of a static check as we can. { // The .NET framework doesn't provide a compile-checked // way to ensure that a type is an enum, so we have to check when the type // is statically invoked. static EnumUtil() { // Throw Exception on static initialization if the given type isn't an enum. Require.That(typeof (T).IsEnum, () => typeof(T).FullName + " is not an enum type."); } ///  /// In the .NET Framework, objects can be cast to enum values which are not /// defined for their type. This method provides a simple fail-fast check /// that the enum value is defined, and creates a cast at the same time. /// Cast the given value as the given enum type. /// Throw an exception if the value is not defined for the given enum type. ///  ///  ///  ///  /// If the given value is not a defined value of the enum type. ///  ///  public static T DefinedCast(object enumValue) { if (!System.Enum.IsDefined(typeof(T), enumValue)) throw new InvalidCastException(enumValue + " is not a defined value for enum type " + typeof (T).FullName); return (T) enumValue; } ///  /// ///  ///  ///  public static T Parse(string enumValue) { var parsedValue = (T)System.Enum.Parse(typeof (T), enumValue); //Require that the parsed value is defined Require.That(parsedValue.IsDefined(), () => new ArgumentException(string.Format("{0} is not a defined value for enum type {1}", enumValue, typeof(T).FullName))); return parsedValue; } public static bool IsDefined(T enumValue) { return System.Enum.IsDefined(typeof (T), enumValue); } } public static class EnumExtensions { public static bool IsDefined(this T enumValue) where T : struct, IConvertible { return EnumUtil.IsDefined(enumValue); } } 

这样,我可以说:

 if(!sEnum.IsDefined()) throw new Exception(...); 

… 要么:

 EnumUtil.Parse(s); // throws an exception if s is not a defined value. 

枚举在技术上只是一个int(或者你已经定义了enum的底层类型)。 您可以检查枚举中的相应值,但调用Enum.IsDefined 。 更多信息: 在C#中将int转换为枚举

枚举对于int来说真的很薄。 基本上它是int +静态的可能值集合(常量)。 所有的检查都是在编译时,类型检查等。但是当你实际将intenum运行时并不关心。 所以validation您的输入!

如果在传递的值不可解析的情况下抛出exception,请使用int.Parse()。 如果要在不抛出exception的情况下解析可能无效的值,请使用int.TryParse()。