Pergunta

Eu gostaria de criar um método genérico para converter qualquer tipo derivado System.Enum ao seu valor inteiro correspondente, sem fundição e de preferência sem analisar uma string.

Por exemplo, o que eu quero é algo como isto:

// Trivial example, not actually what I'm doing.
class Converter
{
    int ToInteger(System.Enum anEnum)
    {
        (int)anEnum;
    }
}

Mas isso não parece trabalho. relatórios ReSharper que você não pode lançar expressão do tipo 'System.Enum' para digitar 'int'.

Agora que eu vim acima com esta solução, mas eu prefiro ter algo mais eficiente.

class Converter
{
    int ToInteger(System.Enum anEnum)
    {
        return int.Parse(anEnum.ToString("d"));
    }
}

Todas as sugestões?

Foi útil?

Solução

Se você não quer fundido,

Convert.ToInt32()

poderia fazer o truque.

O elenco direta (via (int)enumValue) não é possível. Note-se que isso também seria "perigoso", já que uma enumeração pode ter diferentes tipos subjacentes (int, long, byte ...).

Mais formalmente: System.Enum tem nenhuma relação herança direta com Int32 (embora ambos sejam ValueTypes), assim que o elenco explícito não pode ser correto dentro do sistema de tipo

Outras dicas

Eu tenho que trabalhar, lançando a um objeto e, em seguida, para um int:

public static class EnumExtensions
{
    public static int ToInt(this Enum enumValue)
    {
        return (int)((object)enumValue);
    }
}

Esta é feio e provavelmente não é o melhor caminho. Vou manter mexer com ele, para ver se consigo chegar a algo melhor ....

EDIT: estava prestes a post que Convert.ToInt32 (EnumValue) funciona tão bem, e notou que MartinStettner chegou antes de mim

.
public static class EnumExtensions
{
    public static int ToInt(this Enum enumValue)
    {
        return Convert.ToInt32(enumValue);
    }
}

Test:

int x = DayOfWeek.Friday.ToInt();
Console.WriteLine(x); // results in 5 which is int value of Friday

EDIT 2: Nos comentários, alguém disse que isso só funciona em C # 3.0. Eu só testei isso no VS2005 como este e funcionou:

public static class Helpers
{
    public static int ToInt(Enum enumValue)
    {
        return Convert.ToInt32(enumValue);
    }
}

    static void Main(string[] args)
    {
        Console.WriteLine(Helpers.ToInt(DayOfWeek.Friday));
    }

Se você precisa converter qualquer enum para seu tipo subjacente (nem todos os enums são apoiados por int), então você pode usar:

return System.Convert.ChangeType(
    enumValue,
    Enum.GetUnderlyingType(enumValue.GetType()));

Por que você precisa de reinventar a roda com um método auxiliar? É perfeitamente legal para lançar um valor enum ao seu tipo subjacente.

É menos digitação, e na minha opinião mais legível, para usar ...

int x = (int)DayOfWeek.Tuesday;

... em vez de algo como ...

int y = Converter.ToInteger(DayOfWeek.Tuesday);
// or
int z = DayOfWeek.Tuesday.ToInteger();

De minha resposta aqui :

Dada e como em:

Enum e = Question.Role;

Em seguida, esses trabalhos:

int i = Convert.ToInt32(e);
int i = (int)(object)e;
int i = (int)Enum.Parse(e.GetType(), e.ToString());
int i = (int)Enum.ToObject(e.GetType(), e);

Os dois últimos são feio. O primeiro deverá ser mais legível, embora o segundo é muito mais rápido. Ou pode ser um método de extensão é o melhor, o melhor dos dois mundos.

public static int GetIntValue(this Enum e)
{
    return e.GetValue<int>();
}

public static T GetValue<T>(this Enum e) where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
{
    return (T)(object)e;
}

Agora você pode ligar no:

e.GetValue<int>(); //or
e.GetIntValue();

Moldagem de um System.Enum a um int fina funciona para mim (é também sobre o MSDN ). Talvez seja um bug ReSharper.

Desde Enums são restritos a byte, sbyte, short, ushort, int, uint, longo e ulong, podemos fazer algumas suposições.

Podemos evitar exceções durante a conversão usando o maior recipiente disponível. Infelizmente, o que recipiente para utilização não está claro porque ulong vai explodir para números negativos e tempo vai explodir para números entre long.MaxValue e ulong.MaxValue. Precisamos alternar entre estas escolhas com base no tipo subjacente.

Claro, você ainda precisa decidir o que fazer quando o resultado não se encaixa dentro de um int. Acho elenco é bom, mas ainda existem algumas armadilhas:

  1. para enums com base em um tipo com um espaço de campo maior do que int (longa e ULONG), é possível que alguns enums irá avaliar para o mesmo valor.
  2. lançando um número maior do que int.MaxValue irá lançar uma exceção se você estiver em uma região marcada.

Aqui está a minha sugestão, eu vou deixar para o leitor a decidir onde para expor essa função; como um auxiliar ou uma extensão.

public int ToInt(Enum e)
{
  unchecked
  {
    if (e.GetTypeCode() == TypeCode.UInt64)
      return (int)Convert.ToUInt64(e);
    else
      return (int)Convert.ToInt64(e);
  }
}

Não se esqueça que o tipo Enum em si tem um monte de funções auxiliares estáticos na mesma. Se tudo que você quer fazer é converter uma instância do enum para seu tipo inteiro correspondente, em seguida, lançando é provavelmente a maneira mais eficiente.

Eu acho que ReSharper está reclamando porque Enum não é uma enumeração de qualquer tipo particular, e os próprios enumerações derivar de uma valuetype escalar, não Enum. Se você precisa de elenco adaptável de forma genérica, eu diria que isso poderia atendam-lo bem (nota que o próprio tipo de enumeração também está incluído no genérico:

public static EnumHelpers
{
    public static T Convert<T, E>(E enumValue)
    {
        return (T)enumValue;
    }
}

Este poderia então ser usado assim:

public enum StopLight: int
{
    Red = 1,
    Yellow = 2,
    Green = 3
}

// ...

int myStoplightColor = EnumHelpers.Convert<int, StopLight>(StopLight.Red);

Eu não posso dizer com certeza fora do topo da minha cabeça, mas o código acima pode até ser apoiada por inferência de tipo C # 's, permitindo o seguinte:

int myStoplightColor = EnumHelpers.Convert<int>(StopLight.Red);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top