with - if enum c#




Elenco int para enum em c# (14)

Como um int pode ser convertido em um enum em c #?


Às vezes você tem um objeto para o tipo MyEnum . Gostar

var MyEnumType = typeof(MyEnumType);

Então:

Enum.ToObject(typeof(MyEnum), 3)

A seguir, um método de extensão ligeiramente melhor

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

Apenas lance:

MyEnum e = (MyEnum)3;

Você pode verificar se está no intervalo usando Enum.IsDefined :

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

Como alternativa, use um método de extensão em vez de um 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>();

De uma string:

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

De um int:

YourEnum foo = (YourEnum)yourInt;

Atualizar:

Do numero voce tambem pode

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

Diferentes maneiras de lançar para e 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);


 }
}

Este é um método de conversão seguro com reconhecimento de enumeração de sinalizadores:

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: struct
{
  var enumType = typeof (T);
  if (!enumType.IsEnum)
  {
    throw new ArgumentException("The generic type must be an enum.");
  }
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}

Eu acho que para obter uma resposta completa, as pessoas precisam saber como enums funcionam internamente no .NET.

Como as coisas funcionam

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

public enum Foo : short

Nesse caso, o enum é mapeado para o tipo de dados short , o que significa que ele será armazenado na memória como um curto e se comportará como um curto quando você converter e usar.

Se você olhar de um ponto de vista IL, um enum (normal, int) se parece com isto:

.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 chamar sua atenção aqui é que o value__ é armazenado separadamente dos valores enum. No caso do enum Foo acima, o tipo de value__ é int16. Isso basicamente significa que você pode armazenar o que quiser em um enum, contanto que os tipos correspondam .

Neste ponto, gostaria de salientar que System.Enum é um tipo de valor, que basicamente significa que o BarFlag ocupará 4 bytes na memória e o Foo ocupará 2 - por exemplo, o tamanho do tipo subjacente (na verdade, é mais complicado do que isso, mas hey ...).

A resposta

Portanto, se você tiver um inteiro que deseja mapear para um enum, o tempo de execução só precisa fazer duas coisas: copiar os 4 bytes e nomeá-lo como outra coisa (o nome do enum). A cópia é implícita porque os dados são armazenados como tipo de valor - isso basicamente significa que, se você usar código não gerenciado, poderá simplesmente trocar enums e inteiros sem copiar dados.

Para torná-lo seguro, acho que é uma prática recomendada saber que os tipos subjacentes são os mesmos ou implicitamente conversíveis e garantir que os valores enum existam (eles não são verificados 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 o casting para e2 também funciona! Da perspectiva do compilador acima, isso faz sentido: o campo value__ é simplesmente preenchido com 5 ou 6 e quando Console.WriteLine chama ToString() , o nome de e1 é resolvido enquanto o nome de e2 não é.

Se não for o que você pretendia, use Enum.IsDefined(typeof(MyEnum), 6) para verificar se o valor que você está convertendo mapeia para um enum definido.

Observe também que sou explícito sobre o tipo subjacente do enum, mesmo que o compilador realmente verifique isso. Estou fazendo isso para garantir que não me deparo com surpresas no futuro. Para ver essas surpresas em ação, você pode usar o seguinte código (na verdade, vi isso acontecer muito no código do banco de dados):

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

Eu não sei mais onde eu recebo a parte desta extensão enum, mas é do . Desculpe-me por isto! Mas eu peguei este e modifiquei para enums com Flags. Para enums com Flags 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;

Isso analisa inteiros ou strings para um enum de destino com correspondência parcial no dot.NET 4.0 usando genéricos como na classe de utilitários de Tawani acima. Eu estou usando para converter variáveis ​​de opção de linha de comando que podem estar incompletas. Como um enum não pode ser nulo, você deve fornecer logicamente um valor padrão. 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 questão era sobre inteiros, que ninguém mencionou também explicitamente converter em Enum.TryParse ()


Para valores numéricos, isso é mais seguro, já que ele retornará um objeto não importando 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;
    }
}


Tome o seguinte exemplo:

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

Um pouco se afastando da pergunta original, mas eu encontrei uma resposta para a pergunta de estouro de pilha Obter valor int do enum útil. Crie uma classe estática com propriedades public const int , permitindo que você colete facilmente um conjunto de constantes int relacionadas e, em seguida, não tenha que convertê-las em int ao usá-las.

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, algumas das funcionalidades do tipo enum serão perdidas, mas para armazenar um monte de constantes de id do banco de dados, parece uma solução bem arrumada.







casting