Eu gostaria de criar um método genérico para converter qualquer tipo derivado de System.Enum em seu valor inteiro correspondente, sem converter e, de preferência, sem analisar uma string.
Por exemplo, o que eu quero é algo assim:
// Trivial example, not actually what I'm doing.
class Converter
{
int ToInteger(System.Enum anEnum)
{
(int)anEnum;
}
}
Mas isso não parece funcionar. Resharper relata que você não pode converter uma expressão do tipo 'System.Enum' para o tipo 'int'.
Agora eu vim com essa solução, mas prefiro algo mais eficiente.
class Converter
{
int ToInteger(System.Enum anEnum)
{
return int.Parse(anEnum.ToString("d"));
}
}
Alguma sugestão?
c#
enums
type-conversion
orj
fonte
fonte
Respostas:
Se você não quiser lançar,
poderia fazer o truque.
O cast direto (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
não tem relação de herança direta comInt32
(embora ambos sejamValueType
s), então a conversão explícita não pode ser correta dentro do sistema de tipofonte
Converter.ToInteger(MyEnum.MyEnumConstant);
não dará nenhum erro aqui. Edite essa parte.int
long
enum.System.Enum
é uma classe, portanto, é um tipo de referência. Os valores provavelmente estão em caixas.Comecei a trabalhar lançando para um objeto e depois para um int:
Isso é feio e provavelmente não é a melhor maneira. Vou continuar mexendo nisso, para ver se consigo encontrar algo melhor ...
EDIT: Estava prestes a postar que Convert.ToInt32 (enumValue) funciona bem, e percebi que MartinStettner chegou antes de mim.
Teste:
EDIT 2: Nos comentários, alguém disse que isso só funciona em C # 3.0. Acabei de testar isso no VS2005 assim e funcionou:
fonte
Se precisar converter qualquer enum em seu tipo subjacente (nem todos os enums são apoiados por
int
), você pode usar:fonte
Convert.ChangeType
aceitaobject
como primeiro argumento e retornaobject
.Por que você precisa reinventar a roda com um método auxiliar? É perfeitamente legal lançar um
enum
valor para seu tipo subjacente.É menos digitação e na minha opinião mais legível para usar ...
... em vez de algo como ...
fonte
Da minha resposta aqui :
Dado
e
como em:Então estes funcionam:
Os dois últimos são completamente feios. O primeiro deve ser mais legível, embora o segundo seja muito mais rápido. Ou pode ser que um método de extensão seja o melhor, o melhor dos dois mundos.
Agora você pode ligar para:
fonte
e
variável já tem a instância em caixa do tipo de valor real, ou seja, enum. Quando você escreveEnum e = Question.Role;
, já está encaixotado. A questão é sobre como converter o tipo de caixa deSystem.Enum
volta para o tipo int subjacente (unboxing). Portanto, a unboxing é apenas a questão do desempenho.(int)(object)e
é uma chamada desencaixotada direta; sim deve ser mais rápido do que outras abordagens. Veja istoTransmitir de um
System.Enum
para umint
funciona bem para mim (também está no MSDN ). Talvez seja um bug do Resharper.fonte
System.Enum
, nãoSystem.Enum
ele mesmo.Como os Enums são restritos a byte, sbyte, short, ushort, int, uint, long e ulong, podemos fazer algumas suposições.
Podemos evitar exceções durante a conversão usando o maior contêiner disponível. Infelizmente, qual recipiente usar não está claro porque ulong explodirá para números negativos e long irá explodir para números entre long.MaxValue e ulong.MaxValue. Precisamos alternar entre essas opções com base no tipo subjacente.
Claro, você ainda precisa decidir o que fazer quando o resultado não couber dentro de um int. Acho que o elenco está bem, mas ainda existem algumas pegadinhas:
Aqui está minha sugestão, vou deixar para o leitor decidir onde expor esta função; como ajudante ou extensão.
fonte
Não se esqueça de que o próprio tipo Enum contém várias funções auxiliares estáticas. Se tudo o que você deseja fazer é converter uma instância do enum em seu tipo inteiro correspondente, a conversão é provavelmente a maneira mais eficiente.
Acho que ReSharper está reclamando porque Enum não é uma enumeração de nenhum tipo específico, e as próprias enumerações derivam de um tipo de valor escalar, não Enum. Se você precisar de elenco adaptável de uma forma genérica, eu diria que isso pode servir para você (observe que o próprio tipo de enumeração também está incluído no genérico:
Isso poderia então ser usado da seguinte forma:
Não posso dizer com certeza de cara, mas o código acima pode até ser compatível com a inferência de tipo do C #, permitindo o seguinte:
fonte
EnumHelpers.Convert<int, StopLight>(StopLight.Red);
vez de(int)StopLight.Read;
? Também a questão está falandoSystem.Enum
.