Cast int to enum in C#
如何在一个
从字符串:
1 2 3 4 | YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString); // the foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(",")) throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.") |
从int:
1 | YourEnum foo = (YourEnum)yourInt; |
更新:
从数字上你也可以
1 |
只是投下:
1 | MyEnum e = (MyEnum)3; |
您可以使用Enum.IsDefined检查它是否在范围内:
1 |
或者,使用扩展方法而不是一个衬板:
1 2 3 4 | public static T ToEnum<T>(this string enumString) { return (T) Enum.Parse(typeof (T), enumString); } |
用途:
1 | Color colorEnum ="Red".ToEnum<Color>(); |
或
1 2 | string color ="Red"; var colorEnum = color.ToEnum<Color>(); |
我认为要得到一个完整的答案,人们必须知道Enums如何在.NET内部工作。
素材如何工作
.NET中的枚举是将一组值(字段)映射到基本类型(默认值为
1 | public enum Foo : short |
在这种情况下,枚举被映射到
如果从IL的角度来看,则(normal,int)枚举如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | .class public auto ansi serializable sealed BarFlag extends System.Enum { .custom instance void System.FlagsAttribute::.ctor() .custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) } .field public static literal valuetype BarFlag AllFlags = int32(0x3fff) .field public static literal valuetype BarFlag Foo1 = int32(1) .field public static literal valuetype BarFlag Foo2 = int32(0x2000) // and so on for all flags or enum values .field public specialname rtspecialname int32 value__ } |
您应该注意的是,
我想指出的是,
答案
因此,如果您有一个要映射到枚举的整数,那么运行时只需要做两件事:复制4个字节,并将其命名为其他东西(枚举的名称)。复制是隐式的,因为数据存储为值类型——这基本上意味着如果使用非托管代码,则可以简单地交换枚举和整数而不复制数据。
为了安全起见,我认为最好的做法是知道基础类型是相同的或隐式可转换的,并确保枚举值存在(默认情况下不会检查它们!).
要了解这是如何工作的,请尝试以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public enum MyEnum : int { Foo = 1, Bar = 2, Mek = 5 } static void Main(string[] args) { var e1 = (MyEnum)5; var e2 = (MyEnum)6; Console.WriteLine("{0} {1}", e1, e2); Console.ReadLine(); } |
注意,铸造到
如果这不是您想要的,请使用
另外请注意,我对枚举的基础类型很明确,即使编译器实际上检查了这一点。我这样做是为了确保我不会在路上遇到任何意外。要看到这些意外的行为,您可以使用以下代码(实际上,我在数据库代码中看到过很多这样的情况):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public enum MyEnum : short { Mek = 5 } static void Main(string[] args) { var e1 = (MyEnum)32769; // will not compile, out of bounds for a short object o = 5; var e2 = (MyEnum)o; // will throw at runtime, because o is of type int Console.WriteLine("{0} {1}", e1, e2); Console.ReadLine(); } |
例如:
1 2 | int one = 1; MyEnum e = (MyEnum)one; |
我使用这段代码将int强制转换为枚举:
1 2 | if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast; else { //handle it here, if its not defined } |
我觉得这是最好的解决办法。
下面是一个很好的枚举实用程序类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public static class EnumHelper { public static int[] ToIntArray<T>(T[] value) { int[] result = new int[value.Length]; for (int i = 0; i < value.Length; i++) result[i] = Convert.ToInt32(value[i]); return result; } public static T[] FromIntArray<T>(int[] value) { T[] result = new T[value.Length]; for (int i = 0; i < value.Length; i++) result[i] = (T)Enum.ToObject(typeof(T),value[i]); return result; } internal static T Parse<T>(string value, T defaultValue) { if (Enum.IsDefined(typeof(T), value)) return (T) Enum.Parse(typeof (T), value); int num; if(int.TryParse(value,out num)) { if (Enum.IsDefined(typeof(T), num)) return (T)Enum.ToObject(typeof(T), num); } return defaultValue; } } |
对于数值,这是更安全的,因为它将返回一个对象,无论是什么:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
如果您已经准备好使用4.0.NET框架,那么有一个新的enum.typarse()函数非常有用,并且可以很好地使用[flags]属性。请参见enum.typarse方法(string,tenum%)。
如果有一个整数充当位掩码,并且可以在[Flags]枚举中表示一个或多个值,则可以使用此代码将各个标志值解析为列表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | for (var flagIterator = 0; flagIterator < 32; flagIterator++) { // Determine the bit value (1,2,4,...,Int32.MinValue) int bitValue = 1 << flagIterator; // Check to see if the current flag exists in the bit mask if ((intValue & bitValue) != 0) { // If the current flag exists in the enumeration, then we can add that value to the list // if the enumeration has that flag defined if (Enum.IsDefined(typeof(MyEnum), bitValue)) Console.WriteLine((MyEnum)bitValue); } } |
注意,这假设
有时,您有一个针对
1 |
然后:
1 |
这是一个标记枚举感知的安全转换方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public static bool TryConvertToEnum<T>(this int instance, out T result) where T: Enum { var enumType = typeof (T); var success = Enum.IsDefined(enumType, instance); if (success) { result = (T)Enum.ToObject(enumType, instance); } else { result = default(T); } return success; } |
要将字符串转换为枚举或将int转换为枚举常量,需要使用Enum.Parse函数。这是YouTube视频https://www.youtube.com/watch?v=4nhx4vwdrdk,它实际上用字符串来演示,同样适用于int。
代码如下所示,其中"red"是字符串,"mycolors"是具有颜色常量的颜色枚举。
1 |
稍微远离原始问题,但我发现堆栈溢出问题的答案"从枚举中获取int值"很有用。使用
1 2 3 4 5 6 7 8 | public static class Question { public static readonly int Role = 2; public static readonly int ProjectFunding = 3; public static readonly int TotalEmployee = 4; public static readonly int NumberOfServers = 5; public static readonly int TopBusinessConcern = 6; } |
显然,一些枚举类型的功能将丢失,但对于存储一堆数据库ID常量来说,这似乎是一个非常整洁的解决方案。
这将使用上面tawani的实用程序类中的泛型,将整数或字符串解析为在dot.net 4.0中部分匹配的目标枚举。我使用它来转换可能不完整的命令行开关变量。由于枚举不能为空,因此应在逻辑上提供默认值。可以这样称呼:
1 | var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue); |
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | using System; public class EnumParser<T> where T : struct { public static T Parse(int toParse, T defaultVal) { return Parse(toParse +"", defaultVal); } public static T Parse(string toParse, T defaultVal) { T enumVal = defaultVal; if (defaultVal is Enum && !String.IsNullOrEmpty(toParse)) { int index; if (int.TryParse(toParse, out index)) { Enum.TryParse(index +"", out enumVal); } else { if (!Enum.TryParse<T>(toParse +"", true, out enumVal)) { MatchPartialName(toParse, ref enumVal); } } } return enumVal; } public static void MatchPartialName(string toParse, ref T enumVal) { foreach (string member in enumVal.GetType().GetEnumNames()) { if (member.ToLower().Contains(toParse.ToLower())) { if (Enum.TryParse<T>(member +"", out enumVal)) { break; } } } } } |
仅供参考:这个问题是关于整数的,没有人提到它也将在enum.typarse()中显式转换。
从字符串:(enum.parse已过期,请使用enum.typarse)
1 2 3 4 5 6 7 8 | enum Importance {} Importance importance; if (Enum.TryParse(value, out importance)) { } |
下面是稍微好一点的扩展方法
1 2 3 4 5 6 7 8 9 |
在我的例子中,我需要从WCF服务返回枚举。我还需要一个友好的名称,而不仅仅是enum.toString()。
这是我的WCF课程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | [DataContract] public class EnumMember { [DataMember] public string Description { get; set; } [DataMember] public int Value { get; set; } public static List<EnumMember> ConvertToList<T>() { Type type = typeof(T); if (!type.IsEnum) { throw new ArgumentException("T must be of type enumeration."); } var members = new List<EnumMember>(); foreach (string item in System.Enum.GetNames(type)) { var enumType = System.Enum.Parse(type, item); members.Add( new EnumMember() { Description = enumType.GetDescriptionValue(), Value = ((IConvertible)enumType).ToInt32(null) }); } return members; } } |
下面是从枚举中获取描述的扩展方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public static string GetDescriptionValue<T>(this T source) { FieldInfo fileInfo = source.GetType().GetField(source.ToString()); DescriptionAttribute[] attributes = (DescriptionAttribute[])fileInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes != null && attributes.Length > 0) { return attributes[0].Description; } else { return source.ToString(); } } |
实施:
1 | return EnumMember.ConvertToList<YourType>(); |
我不知道从哪里得到这个枚举扩展的一部分,但它来自stackoverflow。对不起!但我拿了这个,并修改了它作为带标记的枚举。对于带标志的枚举,我执行了以下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | public static class Enum<T> where T : struct { private static readonly IEnumerable<T> All = Enum.GetValues(typeof (T)).Cast<T>(); private static readonly Dictionary<int, T> Values = All.ToDictionary(k => Convert.ToInt32(k)); public static T? CastOrNull(int value) { T foundValue; if (Values.TryGetValue(value, out foundValue)) { return foundValue; } // For enums with Flags-Attribut. try { bool isFlag = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0; if (isFlag) { int existingIntValue = 0; foreach (T t in Enum.GetValues(typeof(T))) { if ((value & Convert.ToInt32(t)) > 0) { existingIntValue |= Convert.ToInt32(t); } } if (existingIntValue == 0) { return null; } return (T)(Enum.Parse(typeof(T), existingIntValue.ToString(), true)); } } catch (Exception) { return null; } return null; } } |
例子:
1 2 3 4 5 6 7 8 9 10 11 | [Flags] public enum PetType { None = 0, Dog = 1, Cat = 2, Fish = 4, Bird = 8, Reptile = 16, Other = 32 }; integer values 1=Dog; 13= Dog | Fish | Bird; 96= Other; 128= Null; |
向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | enum orientation : byte { north = 1, south = 2, east = 3, west = 4 } class Program { static void Main(string[] args) { orientation myDirection = orientation.north; Console.WriteLine("myDirection = {0}", myDirection); //output myDirection =north Console.WriteLine((byte)myDirection); //output 1 string strDir = Convert.ToString(myDirection); Console.WriteLine(strDir); //output north string myString ="north"; //to convert string to Enum myDirection = (orientation)Enum.Parse(typeof(orientation),myString); } } |
它可以帮助您将任何输入数据转换为用户所需的枚举。假设您有一个枚举,如下所示,默认为int。请在枚举的第一个处添加一个默认值。当与输入值不匹配时,用于帮助者medthod。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public enum FriendType { Default, Audio, Video, Image } public static class EnumHelper<T> { public static T ConvertToEnum(dynamic value) { var result = default(T); var tempType = 0; //see Note below if (value != null && int.TryParse(value.ToString(), out tempType) && Enum.IsDefined(typeof(T), tempType)) { result = (T)Enum.ToObject(typeof(T), tempType); } return result; } } |
注意:这里我尝试将值解析为int,因为枚举默认为int。如果您像这样定义枚举,它是字节类型。
1 2 3 4 5 6 7 | public enum MediaType : byte { Default, Audio, Video, Image } |
您需要将helper方法的解析从
1 | int.TryParse(value.ToString(), out tempType) |
到
我检查我的方法是否有以下输入
1 2 3 4 5 6 7 8 9 10 | EnumHelper<FriendType>.ConvertToEnum(null); EnumHelper<FriendType>.ConvertToEnum(""); EnumHelper<FriendType>.ConvertToEnum("-1"); EnumHelper<FriendType>.ConvertToEnum("6"); EnumHelper<FriendType>.ConvertToEnum(""); EnumHelper<FriendType>.ConvertToEnum("2"); EnumHelper<FriendType>.ConvertToEnum(-1); EnumHelper<FriendType>.ConvertToEnum(0); EnumHelper<FriendType>.ConvertToEnum(1); EnumHelper<FriendType>.ConvertToEnum(9); |
对不起我的英语
用C将int强制枚举的简单而清晰的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class Program { public enum Color : int { Blue = 0, Black = 1, Green = 2, Gray = 3, Yellow =4 } public static void Main(string[] args) { //from string Console.WriteLine((Color) Enum.Parse(typeof(Color),"Green")); //from int Console.WriteLine((Color)2); //From number you can also Console.WriteLine((Color)Enum.ToObject(typeof(Color) ,2)); } } |
这里有一个将
它支持按位标记,即使该值高于最大值。例如,如果您有一个可能为1、2和4的枚举,但int是9,那么它将理解为在没有8的情况下为1。这允许您在代码更新之前进行数据更新。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible { if (!typeof(TEnum).IsEnum) { return default(TEnum); } if (Enum.IsDefined(typeof(TEnum), val)) {//if a straightforward single value, return that return (TEnum)Enum.ToObject(typeof(TEnum), val); } var candidates = Enum .GetValues(typeof(TEnum)) .Cast<int>() .ToList(); var isBitwise = candidates .Select((n, i) => { if (i < 2) return n == 0 || n == 1; return n / 2 == candidates[i - 1]; }) .All(y => y); var maxPossible = candidates.Sum(); if ( Enum.TryParse(val.ToString(), out TEnum asEnum) && (val <= maxPossible || !isBitwise) ){//if it can be parsed as a bitwise enum with multiple flags, //or is not bitwise, return the result of TryParse return asEnum; } //If the value is higher than all possible combinations, //remove the high imaginary values not accounted for in the enum var excess = Enumerable .Range(0, 32) .Select(n => (int)Math.Pow(2, n)) .Where(n => n <= val && n > 0 && !candidates.Contains(n)) .Sum(); return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum); } |
只需使用显式转换cast int to enum或enum to int
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class Program { static void Main(string[] args) { Console.WriteLine((int)Number.three); //Output=3 Console.WriteLine((Number)3);// Outout three Console.Read(); } public enum Number { Zero = 0, One = 1, Two = 2, three = 3 } } |