【问题标题】:How can I cast int to enum?如何将 int 转换为枚举?
【发布时间】:2010-09-06 23:12:46
【问题描述】:

如何在 C# 中将 int 强制转换为 enum

【问题讨论】:

    标签: c# enums casting int


    【解决方案1】:

    我更喜欢使用可空枚举类型变量的捷径。

    var enumValue = (MyEnum?)enumInt;
    
    if (!enumValue.HasValue)
    {
        throw new ArgumentException(nameof(enumValue));
    }
    

    【讨论】:

      【解决方案2】:

      有时你有一个MyEnum 类型的对象。喜欢

      var MyEnumType = typeof(MyEnum);
      

      然后:

      Enum.ToObject(typeof(MyEnum), 3)
      

      【讨论】:

        【解决方案3】:
        var result = Enum.TryParse(yourString, out yourEnum) 
        

        并确保检查结果以确定转换是否失败。

        【讨论】:

        • 例如在字符串不是 int 的情况下工作
        【解决方案4】:

        从一个整数:

        YourEnum foo = (YourEnum)yourInt;
        

        从一个字符串:

        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.")
        }
        

        更新:

        从号码你也可以

        YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);
        

        【讨论】:

        • @FlySwat,如果YourEnum 是动态的并且只会在运行时知道,而我想要转换为Enum 怎么办?
        • 请注意,如果您的代码被混淆,Enum.Parse 将不起作用。在混淆后的运行时,将字符串与枚举名称进行比较,此时枚举的名称并不是您期望的那样。结果,您的解析将在之前成功的地方失败。
        • 注意 如果你使用上面的“from a string”语法并传入一个无效的数字字符串(例如“2342342”——假设这不是你的枚举),它实际上会允许这样做而不会引发错误!您的枚举将具有该值 (2342342),即使它不是枚举本身的有效选择。
        • 我认为这个答案现在有点过时了。对于字符串,你现在真的应该使用var result = Enum.TryParse(yourString, out yourEnum)(并检查结果以确定转换是否失败)。
        • 还可以通过在调用中添加true 参数值使Enum.Parse 不区分大小写:YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true);
        【解决方案5】:

        很简单,您可以将 int 转换为枚举

         public enum DaysOfWeeks
            {
                Monday = 1,
                Tuesday = 2,
                Wednesday = 3,
                Thursday = 4,
                Friday = 5,
                Saturday = 6,
                Sunday = 7,
            } 
        
            var day= (DaysOfWeeks)5;
            Console.WriteLine("Day is : {0}", day);
            Console.ReadLine();
        

        【讨论】:

        • 如果演员表有效,您将无法将其存储为 int。
        • 请尝试理解 int 到 Enum 我认为上面的答案可以帮助你。
        【解决方案6】:

        这会在 .NET 4.0 中使用像 Tawani's utility class 中的泛型将整数或字符串解析为具有部分匹配的目标枚举。我正在使用它来转换可能不完整的命令行开关变量。由于枚举不能为空,因此您应该在逻辑上提供默认值。可以这样调用:

        var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);
        

        代码如下:

        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.TryParse() 中显式转换

        【讨论】:

          【解决方案7】:

          下面是稍微好一点的扩展方法:

          public static string ToEnumString<TEnum>(this int enumValue)
          {
              var enumString = enumValue.ToString();
              if (Enum.IsDefined(typeof(TEnum), enumValue))
              {
                  enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
              }
              return enumString;
          }
          

          【讨论】:

          • 这实际上要好得多,因为如果 int 值不是枚举中定义的条目,您可以使用 else 语句将 enumString 设置为默认值。谢谢
          【解决方案8】:

          在 C# 中将 int 转换为枚举的简单明了的方法:

          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));
              }
          }
          

          【讨论】:

            【解决方案9】:

            您可以使用扩展方法。

            public static class Extensions
            {
            
                public static T ToEnum<T>(this string data) where T : struct
                {
                    if (!Enum.TryParse(data, true, out T enumVariable))
                    {
                        if (Enum.IsDefined(typeof(T), enumVariable))
                        {
                            return enumVariable;
                        }
                    }
            
                    return default;
                }
            
                public static T ToEnum<T>(this int data) where T : struct
                {
                    return (T)Enum.ToObject(typeof(T), data);
                }
            }
            

            像下面的代码一样使用它:

            枚举:

            public enum DaysOfWeeks
            {
                Monday = 1,
                Tuesday = 2,
                Wednesday = 3,
                Thursday = 4,
                Friday = 5,
                Saturday = 6,
                Sunday = 7,
            }
            

            用法:

             string Monday = "Mon";
             int Wednesday = 3;
             var Mon = Monday.ToEnum<DaysOfWeeks>();
             var Wed = Wednesday.ToEnum<DaysOfWeeks>();
            

            【讨论】:

              【解决方案10】:

              我需要两条指令:

              YourEnum possibleEnum = (YourEnum)value; // There isn't any guarantee that it is part of the enum
              if (Enum.IsDefined(typeof(YourEnum), possibleEnum))
              {
                  // Value exists in YourEnum
              }
              

              【讨论】:

                【解决方案11】:

                您只需使用显式转换将 int 转换为 enum 或将 enum 转换为 int

                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
                    }
                }
                

                【讨论】:

                  【解决方案12】:
                  using System;
                  using System.Collections.Generic;
                  using System.Linq;
                  using System.Text.RegularExpressions;
                  
                  namespace SamplePrograme
                  {
                      public class Program
                      {
                          public enum Suit : int
                          {
                              Spades = 0,
                              Hearts = 1,
                              Clubs = 2,
                              Diamonds = 3
                          }
                  
                          public static void Main(string[] args)
                          {
                              //from string
                              Console.WriteLine((Suit) Enum.Parse(typeof(Suit), "Clubs"));
                  
                              //from int
                              Console.WriteLine((Suit)1);
                  
                              //From number you can also
                              Console.WriteLine((Suit)Enum.ToObject(typeof(Suit) ,1));
                          }
                      }
                  }
                  

                  【讨论】:

                    【解决方案13】:

                    您应该构建一些类型匹配的松弛以更加健壮。

                    public static T ToEnum<T>(dynamic value)
                    {
                        if (value == null)
                        {
                            // default value of an enum is the object that corresponds to
                            // the default value of its underlying type
                            // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table
                            value = Activator.CreateInstance(Enum.GetUnderlyingType(typeof(T)));
                        }
                        else if (value is string name)
                        {
                            return (T)Enum.Parse(typeof(T), name);
                        }
                    
                        return (T)Enum.ToObject(typeof(T),
                                 Convert.ChangeType(value, Enum.GetUnderlyingType(typeof(T))));
                    }
                    

                    测试用例

                    [Flags]
                    public enum A : uint
                    {
                        None  = 0, 
                        X     = 1 < 0,
                        Y     = 1 < 1
                    }
                    
                    static void Main(string[] args)
                    {
                        var value = EnumHelper.ToEnum<A>(7m);
                        var x = value.HasFlag(A.X); // true
                        var y = value.HasFlag(A.Y); // true
                    
                        var value2 = EnumHelper.ToEnum<A>("X");
                    
                        var value3 = EnumHelper.ToEnum<A>(null);
                    
                        Console.ReadKey();
                    }
                    

                    【讨论】:

                    • 这是一个很好的答案。很遗憾,它目前在页面下方!
                    【解决方案14】:

                    你只需像下面这样:

                    int intToCast = 1;
                    TargetEnum f = (TargetEnum) intToCast ;
                    

                    为了确保你只转换了正确的值,否则你可以抛出异常:

                    int intToCast = 1;
                    if (Enum.IsDefined(typeof(TargetEnum), intToCast ))
                    {
                        TargetEnum target = (TargetEnum)intToCast ;
                    }
                    else
                    {
                       // Throw your exception.
                    }
                    

                    请注意,使用 IsDefined 的成本很高,甚至不仅仅是强制转换,因此取决于您的实现来决定是否使用它。

                    【讨论】:

                      【解决方案15】:

                      这是一个将Int32 转换为Enum 的扩展方法。

                      即使值高于可能的最大值,它也会尊重按位标志。例如,如果你有一个枚举可能有 124,但 int 是 9,在没有 8 的情况下,它理解为 1。这使您可以在代码更新之前进行数据更新。

                         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);
                          }
                      

                      【讨论】:

                        【解决方案16】:

                        如果您有一个整数作为位掩码并且可以表示 [Flags] 枚举中的一个或多个值,则可以使用此代码将各个标志值解析为一个列表:

                        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);
                            }
                        }
                        

                        请注意,这假定enum 的基础类型是带符号的 32 位整数。如果它是不同的数字类型,则必须更改硬编码的 32 以反映该类型中的位(或使用Enum.GetUnderlyingType() 以编程方式派生它)

                        【讨论】:

                          【解决方案17】:

                          这是一个标志枚举感知安全转换方法:

                          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;
                          }
                          

                          【讨论】:

                          • 现在可以使用 C# 7.3 通过限制为 Enum 而不是 struct 来改进这一点,这意味着我们不必依赖运行时检查!
                          【解决方案18】:

                          举个例子:

                          int one = 1;
                          MyEnum e = (MyEnum)one;
                          

                          【讨论】:

                            【解决方案19】:

                            它可以帮助您将任何输入数据转换为用户所需的枚举。假设您有一个如下所示的枚举,默认情况下为 int。请在枚举的开头添加一个 Default 值。当没有找到与输入值匹配时,在辅助方法中使用它。

                            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;
                                }
                            }
                            

                            注意: 这里我尝试将 value 解析为 int,因为 enum 默认为 int 如果你像这样定义枚举,它是 byte 类型。

                            public enum MediaType : byte
                            {
                                Default,
                                Audio,
                                Video,
                                Image
                            } 
                            

                            您需要从

                            更改辅助方法的解析
                            int.TryParse(value.ToString(), out  tempType)
                            

                            byte.TryParse(value.ToString(), out tempType)

                            我检查我的方法是否有以下输入

                            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);
                            

                            对不起我的英语

                            【讨论】:

                              【解决方案20】:

                              稍微偏离了最初的问题,但我发现an answer to Stack Overflow question Get int value from enum 很有用。创建一个具有public const int属性的静态类,让您可以轻松地将一堆相关的int常量收集在一起,然后在使用它们时不必将它们强制转换为int

                              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 常量来说,这似乎是一个非常整洁的解决方案。

                              【讨论】:

                              • 枚举取代了像这样的整数常量的使用,因为它们提供了更多的类型安全
                              • Paul,这是一种将相关的 int 常量(例如数据库 id 常量)收集在一起的方法,因此可以直接使用它们,而不必在每次使用时都将它们强制转换为 int。它们的类型整数,而不是例如DatabaseIdsEnum。
                              • 我发现至少有一种情况可以无意中绕过枚举类型安全性。
                              • 但枚举也确保值都是唯一的,这种方法也缺乏一些东西
                              【解决方案21】:

                              对于数值,这更安全,因为无论如何它都会返回一个对象:

                              public static class EnumEx
                              {
                                  static public bool TryConvert<T>(int value, out T result)
                                  {
                                      result = default(T);
                                      bool success = Enum.IsDefined(typeof(T), value);
                                      if (success)
                                      {
                                          result = (T)Enum.ToObject(typeof(T), value);
                                      }
                                      return success;
                                  }
                              }
                              

                              【讨论】:

                              • 默认(T)未定义时返回。这如何帮助识别未定义的?
                              【解决方案22】:

                              或者,使用扩展方法而不是单行:

                              public static T ToEnum<T>(this string enumString)
                              {
                                  return (T) Enum.Parse(typeof (T), enumString);
                              }
                              

                              用法:

                              Color colorEnum = "Red".ToEnum<Color>();
                              

                              string color = "Red";
                              var colorEnum = color.ToEnum<Color>();
                              

                              【讨论】:

                              • 对于处理用户输入,调用 Enum.Parse 的重载可能是个好主意,它允许您指定比较不区分大小写(即用户键入“red”(小写)如果不进行此更改,上述代码会崩溃。)
                              • 很方便,但这个问题专门询问整数。
                              • 这也适用于字符串是整数的情况,例如“2”
                              • 如果 enumString 为空,这将引发异常(昨天有类似的问题)。考虑使用 TryParse 而不是 Parse。 TryParse 还将检查 T 是否为枚举类型
                              • System.String 这种类型的扩展方法好像是命名空间污染
                              【解决方案23】:

                              我不知道我从哪里得到这个枚举扩展的部分,但它来自 stackoverflow。我对此感到抱歉!但我拿了这个,并为带有标志的枚举修改了它。 对于带有标志的枚举,我这样做了:

                                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;
                                   }
                                }
                              

                              例子:

                              [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;
                              

                              【讨论】:

                                【解决方案24】:

                                从一个字符串:(Enum.Parse 已过期,使用 Enum.TryParse)

                                enum Importance
                                {}
                                
                                Importance importance;
                                
                                if (Enum.TryParse(value, out importance))
                                {
                                }
                                

                                【讨论】:

                                • 该问题专门询问整数。
                                • 余请编辑您的答案,让大家知道 Enum.TryParse 将处理枚举的值或名称的字符串(我无法抗拒)
                                【解决方案25】:

                                就我而言,我需要从 WCF 服务返回枚举。我还需要一个友好的名称,而不仅仅是 enum.ToString()。

                                这是我的 WCF 类。

                                [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;
                                    }
                                }
                                

                                这是从枚举中获取描述的扩展方法。

                                    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();
                                        }
                                    }
                                

                                实施:

                                return EnumMember.ConvertToList<YourType>();
                                

                                【讨论】:

                                  【解决方案26】:

                                  我认为要获得完整的答案,人们必须知道枚举在 .NET 内部是如何工作的。

                                  工作原理

                                  .NET 中的枚举是将一组值(字段)映射到基本类型(默认为int)的结构。但是,您实际上可以选择枚举映射到的整数类型:

                                  public enum Foo : short
                                  

                                  在这种情况下,枚举被映射到short 数据类型,这意味着它将作为短类型存储在内存中,并且在您转换和使用它时将表现为短类型。

                                  如果从 IL 的角度来看,一个 (normal, int) 枚举看起来像这样:

                                  .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__
                                  }
                                  

                                  这里应该引起您注意的是value__ 与枚举值分开存储。在上面的枚举Foo 的情况下,value__ 的类型是 int16。这基本上意味着您可以在枚举中存储您想要的任何内容,只要类型匹配

                                  此时我想指出System.Enum 是一个值类型,这基本上意味着BarFlag 将占用内存中的4 个字节,Foo 将占用2 个字节——例如底层类型的大小(实际上比这更复杂,但是嘿...)。

                                  答案

                                  所以,如果你有一个整数想要映射到一个枚举,运行时只需要做两件事:复制 4 个字节并将其命名为其他名称(枚举的名称)。复制是隐式的,因为数据存储为值类型 - 这基本上意味着如果您使用非托管代码,您可以简单地交换枚举和整数而无需复制数据。

                                  为了安全起见,我认为最好的做法是知道底层类型相同或可隐式转换并确保枚举值存在(默认情况下不检查它们!) .

                                  要查看其工作原理,请尝试以下代码:

                                  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();
                                  }
                                  

                                  请注意,转换为 e2 也可以!从上面的编译器角度来看,这是有道理的:value__ 字段仅填充 5 或 6,当 Console.WriteLine 调用 ToString() 时,e1 的名称被解析,而 e2 的名称则不是。

                                  如果这不是您想要的,请使用 Enum.IsDefined(typeof(MyEnum), 6) 检查您要转换的值是否映射到已定义的枚举。

                                  还要注意,我明确说明了枚举的基础类型,即使编译器实际上会检查这一点。我这样做是为了确保我不会在路上遇到任何意外。要查看这些惊喜的实际效果,您可以使用以下代码(实际上我在数据库代码中经常看到这种情况):

                                  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();
                                  }
                                  

                                  【讨论】:

                                  • 我意识到这是一篇旧文章,但是您如何在 c# 中获得这种水平的知识?这是通过阅读 C# 规范吗?
                                  • @Rolan 我有时希望更多人会这样问。 :-) 老实说,我真的不知道;我试图了解事情是如何运作的,并尽可能地获取信息。我确实阅读了 C# 标准,但我也经常使用 Reflector 反编译代码(我什至经常查看 x86 汇编代码)并进行大量小实验。此外,在这种情况下,了解其他语言也会有所帮助;我已经从事 CS 大约 30 年了,在某些时候某些事情变得“合乎逻辑” - f.ex。枚举应该是整数类型,否则互操作会中断(或者你的性能会下降)。
                                  • 我相信正确进行软件工程的关键是了解事物的工作原理。对我来说,这意味着如果你编写一段代码,你就会知道它是如何大致转换为 f.ex 的。处理器操作和内存读取/写入。如果你问如何达到那个水平,我建议构建大量的小测试用例,让它们变得更难,每次都尝试预测结果,然后进行测试(包括反编译等)。在弄清楚所有细节和所有特征之后,您可以检查您是否在(沉闷的)标准中得到了正确的结果。至少,这将是我的方法。
                                  • 很棒的答案,谢谢!在上一个代码示例中,它在运行时引发异常,因为 o 是一个对象。只要 int 变量在短范围内,您就可以将其转换为 short。
                                  • @gravidThoughts 谢谢。实际上这是一个拆箱操作,所以它不会像你描述的那样做任何隐式转换。如果您不了解细节,在 C# 中强制转换有时会让人感到困惑......无论如何,因为int != short,它会抛出(拆箱失败)。如果您执行object o = (short)5;,它将起作用,因为那样类型将匹配。这与范围无关,而与类型有关。
                                  【解决方案27】:

                                  要将字符串转换为 ENUM 或将 int 转换为 ENUM 常量,我们需要使用 Enum.Parse 函数。这是一个 youtube 视频 https://www.youtube.com/watch?v=4nhx4VwdRDk,它实际上是用字符串演示的,同样适用于 int。

                                  代码如下所示,其中“red”是字符串,“MyColors”是具有颜色常量的颜色 ENUM。

                                  MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
                                  

                                  【讨论】:

                                    【解决方案28】:

                                    Enum

                                    的不同投射方式
                                    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);
                                    
                                    
                                     }
                                    }
                                    

                                    【讨论】:

                                      【解决方案29】:

                                      如果您已准备好使用 4.0 .NET 框架,那么有一个新的 Enum.TryParse() 函数非常有用,并且与 [Flags] 属性配合得很好。见Enum.TryParse Method (String, TEnum%)

                                      【讨论】:

                                      • 这在从字符串转换时很有用。但不是从 int 转换时。
                                      【解决方案30】:

                                      我正在使用这段代码将 int 转换为我的枚举:

                                      if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
                                      else { //handle it here, if its not defined }
                                      

                                      我认为这是最好的解决方案。

                                      【讨论】:

                                      • 这很好。我很惊讶将无效值转换为支持 int 的枚举时没有例外。
                                      • 这实际上与评分最高的答案没有太大区别。该答案还讨论了在将字符串转换为 Enum 类型之后使用 Enum.IsDefined 。所以即使字符串被正确转换,Enum.IsDefined 仍然会捕获它
                                      猜你喜欢
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2011-12-30
                                      • 2013-06-02
                                      • 2013-08-03
                                      • 2012-07-12
                                      相关资源
                                      最近更新 更多