Pergunta

Como pode um int ser convertido para um enum em C#?

Foi útil?

Solução

A partir de uma seqüência de caracteres:

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

A partir de um inteiro:

YourEnum foo = (YourEnum)yourInt;

Atualização:

A partir do número que você também pode

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

Outras dicas

Basta lançá-lo:

MyEnum e = (MyEnum)3;

Você pode verificar se ele está na faixa de utilização Enum.IsDefined:

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }

Como alternativa, use um método de extensão em vez de uma linha:

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

Uso:

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

OU

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

Eu acho que, para obter uma resposta completa, as pessoas têm de saber como enums trabalho internamente .LÍQUIDA.

How stuff works

Um enum em .NET é uma estrutura que mapeia um conjunto de valores (campos) para um tipo básico (o padrão é int).No entanto, você pode escolher o tipo integral que seu enum mapas para:

public enum Foo : short

Neste caso, o enum é mapeado para o short tipo de dados, o que significa que ela vai ser armazenada na memória, como um breve e vai se comportar como um curto ao elenco e usá-lo.

Se você olhar para ele a partir de um IL ponto de vista, um (normal, int) enum parecido com este:

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

O que deve receber a atenção aqui é que a value__ é armazenado separadamente dos valores enum.No caso de o enum Foo acima, o tipo de value__ é int16.Basicamente, isto significa que você pode armazenar o que você quiser em um enum, enquanto os tipos de correspondência.

Neste ponto, eu gostaria de ressaltar que System.Enum é um tipo de valor, o que basicamente significa que BarFlag vai demorar até 4 bytes na memória e Foo vai demorar até 2 -- e.g.o tamanho do tipo subjacente (na verdade é mais complicado do que isso, mas, enfim...).

A resposta

Então, se você tiver um número inteiro que você deseja mapear para um enum, o tempo de execução só tem que fazer 2 coisas:copie os 4 bytes e o nome de outra coisa (o nome do enum).A cópia está implícito, porque os dados são armazenados como tipo de valor - isto significa basicamente que se você usar o código não gerenciado, você pode simplesmente intercâmbio enums e inteiros sem copiar os dados.

Para torná-lo seguro, eu acho que é uma prática recomendada sei que o subjacente tipos são os mesmos, ou implicitamente conversível e para garantir os valores enum existe (eles não são verificadas por padrão!).

Para ver como isso funciona, tente o seguinte código:

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

Note que para fundição e2 também funciona!A partir do compilador acima a perspectiva de que isso faz sentido:o value__ campo é simplesmente cheio de 5 ou 6 e quando Console.WriteLine chamadas ToString(), o nome do e1 é resolvido enquanto o nome de e2 não é.

Se isso não é o que você pretendia, use Enum.IsDefined(typeof(MyEnum), 6) para verificar se o valor que você está fundição de mapas para um número definido de enum.

Também note que eu estou explícita sobre o tipo subjacente do enum, mesmo que o compilador verifica efectivamente isso.Eu estou fazendo isso para garantir que eu não corra para eventuais surpresas para a estrada.Para ver essas surpresas em ação, você pode usar o código a seguir (na verdade, eu já vi isso acontecer muito no banco de dados de código):

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

Tome o seguinte exemplo:

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

Eu estou usando este pedaço de código para lançar int a minha enum:

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

Acho que é a melhor solução.

Abaixo está uma boa classe de utilitário para Enums

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

Para valores numéricos, isso é mais seguro, como ele vai retornar um objeto, não importa o que:

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

Se você está pronto para o 4.0 .NET Quadro, há um novo Enum.TryParse() função que é muito útil e joga muito bem com o atributo [Flags].Ver Enum.Método TryParse (String, TEnum%)

Se você tiver um número inteiro que atua como uma máscara de bits e pode representar um ou mais valores em um [Flags] enumeração, você pode usar este código para analisar o indivíduo bandeira valores em uma lista:

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

Note que isto assume que o tipo subjacente de enum é um inteiro assinado de 32 bits.Se fosse um diferente tipo numérico, você teria que alterar o codificado 32 para refletir os bits em que tipo (ou através de programação derivar-lo usando Enum.GetUnderlyingType())

Às vezes você tem um objeto para o MyEnum escreva.Como

var MyEnumType = typeof(MyEnumType);

Então:

Enum.ToObject(typeof(MyEnum), 3)

Este é um bandeiras enumeração ciente de segurança converter método:

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

enter image description here

Para converter uma string ENUM ou int a ENUMERAÇÃO constante precisamos usar Enum.Função de análise.Aqui está um vídeo do youtube https://www.youtube.com/watch?v=4nhx4VwdRDk o que realmente demonstram com cadeia de caracteres e o mesmo se aplica para int.

O que vai de código, como mostrado abaixo, onde "vermelho" é a seqüência de caracteres e "MyColors" é a cor ENUM que tem a cor constantes.

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

Ligeiramente ficar longe da pergunta original, mas eu achei uma resposta a uma Sobrecarga de Pilha pergunta Obter int valor do enum úteis.Criar uma classe estática com public const int propriedades, permitindo que você facilmente agrupar um monte de relacionados int constantes e, em seguida, não tem que lançá-los para int quando utilizá-los.

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

Obviamente, alguns do tipo enum funcionalidade será perdida, mas para guardar um monte de id de banco de dados constantes, parece muito arrumado solução.

Este analisa números inteiros ou strings para um destino enum com correspondência parcial em dot.NET 4.0 usando genéricos como em Tawani o utilitário da classe acima.Eu estou usando-o para converter opção de linha de comando variáveis que pode estar incompleta.Desde uma enumeração não pode ser null, você deve logicamente fornecer um valor padrão.Ele pode ser chamado assim:

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

Aqui está o código:

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

FYI: A pergunta era sobre números inteiros, que ninguém mencionou também irá converter explicitamente no Enum.TryParse()

A partir de uma seqüência de caracteres:(Enum.Analisar é fora da Data, use Enum.TryParse)

enum Importance
{}

Importance importance;

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

A seguir está um pouco melhor método de extensão

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

No meu caso, eu precisava voltar para a enumeração de um serviço WCF.Eu também precisava de um nome amigável, não apenas o enum.ToString().

Aqui está o meu WCF Classe.

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

Aqui está o método de Extensão que obtém a Descrição do Enum.

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

Implementação:

return EnumMember.ConvertToList<YourType>();

Diferentes formas de elenco e a partir de 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);


 }
}

Eu não sei mais onde eu tiro a parte de enum extensão, mas é a partir do stackoverflow.Eu sinto muito por isso!Mas eu levei um presente e modificado para enums com Bandeiras.Para enums com as Bandeiras que eu fiz isso:

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

Exemplo:

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

Ele pode ajudar você a converter-se qualquer entrada de dados para o usuário desejado enum.Suponha que você tenha um enum, como abaixo que, por padrão, int.Por favor, adicione um Padrão o valor primeiro da sua enumeração.Qual é utilizado em ajudantes medthod quando não há nenhuma correspondência encontrada com o valor de entrada.

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

N. B: Aqui eu tento analisar o valor em int, porque enum é por padrão int Se você definir enum como esta que se byte escreva.

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

Você precisa mudar de análise pelo método auxiliar de

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

para

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

Eu verifico o meu método para os seguintes entradas

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

desculpe pelo meu inglês

Aqui está um método de extensão, que lança Int32 para Enum.

Honra bit a bit bandeiras, mesmo quando o valor é maior do que a máxima possível.Por exemplo, se você tem um enum com possibilidades 1, 2, e 4, mas o int é 9, ele entende que, como 1 na ausência de um 8.Isso permite que você faça atualizações de dados antes do código de atualizações.

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

fácil e claro para fundição de int para enum em c#:

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

Você simplesmente usa Conversão explícita Elenco int enum ou enum para 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           
        }
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top