Eu procurei e não consegui encontrar uma duplicata. Se você pode fornecer um link, eu excluirei esta pergunta.
Eric Weilnau 27/01/09
1
às vezes, usando uma instrução switch não é a melhor prática (quando você tem grandes enumerações) você pode usar Dict <> em vez
Guy L
1
Se você deseja um melhor desempenho, pode usar a classe descrita neste artigo codeproject.com/KB/dotnet/enum.aspx . Uso será parecido com este Enum <YourEnum> .ToString (yourValue) ou Enum <YourEnum> .ToString ((int) yourValue)
ideafixxxer
5
Codificar para não romper a difusão de pontos é o epítome da cauda que sacode o cão. Os produtores de SW não estão pensando: "Vamos criar um ótimo aplicativo para que o dotfuscator tenha algo a fazer". O Dofuscator existe para ajudar a facilitar o desenvolvimento do SW. Se não pode fazer isso ... pode!
Micahhoover
Respostas:
125
A partir do C # 6, a melhor maneira de obter o nome de uma enumeração é o novo nameofoperador:
nameof(MyEnum.EnumValue);// Ouputs>"EnumValue"
Isso funciona em tempo de compilação, com o enum sendo substituído pela string no resultado compilado, o que, por sua vez, significa que esta é a maneira mais rápida possível.
Qualquer uso de nomes de enumerações interfere na ofuscação do código, se você considerar que a ofuscação de nomes de enumerações vale a pena ou é importante - provavelmente essa é outra questão.
Isso merece mais atenção. Não obstante a limitação óbvia, ou seja, o requisito para entrada em tempo de compilação. Na minha opinião, isso deve ser preferido sempre que possível . 'Renomear' e 'encontrar todas as referências' também levam em conta, potencialmente evitando seqüências de caracteres mágicas e constantes duplicadas.
Timo
1
Então eu acho que não vai funcionar quando o valor de enum é definido em tempo de execução? Ex: MyEnum variableEnum; variableEnum = setEnumValueMethod (); nameof (variávelEnum);
Maxter
1
@ Maxter não, como nameof(variableEnum)será "variableEnum". Ele reflete (no tempo de construção) o nome do campo / propriedade / parâmetro / variável e não o valor .
Keith
vós. infelizmente não funciona se você fizer isso: var someEnumvalue = SomeEnum.FooBar; nameof (someEnumvalue);
Squibly 11/11/19
@Squibly sim, que irá retornar "someEnumValue", enquanto você precisaria nameof(SomeEnum.FooBar)para chegar "FooBar".
Enum.GetName leva o valor como um argumento de objeto. Isso significa que o valor será armazenado em caixa e isso desperdiçará recursos da CPU na alocação e na coleta de lixo. Se isso for feito muito tempo, o Enum.GetName terá uma taxa de transferência muito menor do que o cache dos valores em um dicionário e a procura do nome lá.
Ran
@Ran Então, qual é a solução, qual usar?
shaijut
Esta deve ser a resposta
Squibly
torna meu projeto mais lento. toString () é mais rápido.
d2k2 15/06
29
Nos meus testes, Enum.GetNamefoi mais rápido e com margem decente. ToStringChamadas internamente Enum.GetName. Da fonte para o .NET 4.0, o essencial:
publicoverrideStringToString(){returnEnum.InternalFormat((RuntimeType)GetType(),GetValue());}privatestaticStringInternalFormat(RuntimeType eT,Objectvalue){if(!eT.IsDefined(typeof(System.FlagsAttribute),false)){String retval =GetName(eT,value);//<== the oneif(retval ==null)returnvalue.ToString();elsereturn retval;}else{returnInternalFlagsFormat(eT,value);}}
Não posso dizer que esse seja o motivo, com certeza, mas os testes indicam que um é mais rápido que o outro. Ambas as chamadas envolvem boxe (na verdade, são chamadas de reflexão, você está basicamente recuperando nomes de campos) e pode ser lento ao seu gosto.
Configuração do teste : enumeração com 8 valores, no. de iterações = 1000000
Resultado : Enum.GetName => 700 ms, ToString => 2000 ms
Se a velocidade não for perceptível, eu não me importaria e usaria, ToStringpois oferece uma chamada muito mais limpa. Contraste
Tudo isso internamente acaba chamando um método chamado InternalGetValueAsString. A diferença entre ToStringe GetNameseria a que GetNamedeve verificar algumas coisas primeiro:
O tipo digitado não é nulo.
O tipo que você digitou é, de fato, uma enumeração.
O valor que você passou não é nulo.
O valor que você passou é de um tipo que uma enumeração pode realmente usar como tipo subjacente ou do tipo da própria enumeração. Ele usa GetTypeo valor para verificar isso.
.ToStringnão precisa se preocupar com nenhum desses problemas acima, porque é chamado em uma instância da própria classe e não em uma versão passada, portanto, devido ao fato de o .ToStringmétodo não ter os mesmos problemas de verificação como métodos estáticos, eu concluiria que .ToStringé a maneira mais rápida de obter o valor como uma string.
onde você verificou isso? Qual era a versão da montagem? Eu recebo resultados muito diferentes.
Nawfal
17
O melhor que posso encontrar é essa pergunta não relacionada no MSDN , que contém um trecho de código XML que responde a essa pergunta. Qualquer um desses métodos compartilha a mesma falha: eles chamam enum.toString(), o que não funciona corretamente ao usar o Dotfuscation . Outras preocupações parecem estar relacionadas ao boxe indireto (GetName e Format). Infelizmente, não consigo encontrar nenhuma razão de desempenho para usar qualquer uma das opções acima.
Passar uma enumeração em caixa para string.Format () ou qualquer outra função pode resultar em enum.ToString()uma chamada. Isso causará problemas quando o Dotfuscating. Você não deve usar enum.ToString(), enum.GetNames(), enum.GetName(), enum.Format()ou enum.Parse()para converter um enum para uma string. Em vez disso, use uma instrução switch e internacionalize os nomes, se necessário.
Format()é realmente apenas um invólucro GetName()com alguma funcionalidade de formatação (ou InternalGetValueAsString()para ser exato). ToString()é praticamente o mesmo que Format(). Eu acho que GetName()é a melhor opção, pois é totalmente óbvio o que faz para quem lê a fonte.
Crio um método de extensão "Descrição" e o anexo à enumeração para que eu possa obter uma nomeação verdadeiramente amigável que inclua espaços e maiúsculas e minúsculas. Eu nunca gostei de usar o valor enum como texto exibível porque é algo que os desenvolvedores usam para criar um código mais legível. Não se destina a fins de exibição da interface do usuário. Quero poder alterar a interface do usuário sem passar e alterar as enumerações por toda parte.
Não sei qual é o método "preferido" (pergunte a 100 pessoas e obtenha 100 opiniões diferentes), mas faça o que é mais simples e o que funciona. GetNamefunciona, mas requer muito mais pressionamentos de tecla. ToString()parece fazer o trabalho muito bem.
ToString()fornece o resultado mais óbvio do ponto de vista da legibilidade, enquanto usaEnum.GetName() requer uma análise um pouco mais mental para entender rapidamente o que está tentando fazer (a menos que você veja o padrão o tempo todo).
Do ponto de vista do desempenho puro, como já fornecido na resposta do @ nawfal, Enum.GetName()é melhor.
Se o desempenho é realmente o seu objetivo, seria ainda melhor fornecer uma pesquisa prévia (usando um Dicionário ou outro mapeamento).
Em C ++ / CLI, isso seria semelhante
Dictionary<String^,MyEnum> mapping;for each (MyEnum field in Enum::GetValues(MyEnum::typeid)){
mapping.Add(Enum::GetName(MyEnum::typeid), field);}
Comparação usando uma enumeração de 100 itens e 1000000 iterações:
Respostas:
A partir do C # 6, a melhor maneira de obter o nome de uma enumeração é o novo
nameof
operador:Isso funciona em tempo de compilação, com o enum sendo substituído pela string no resultado compilado, o que, por sua vez, significa que esta é a maneira mais rápida possível.
Qualquer uso de nomes de enumerações interfere na ofuscação do código, se você considerar que a ofuscação de nomes de enumerações vale a pena ou é importante - provavelmente essa é outra questão.
fonte
nameof(variableEnum)
será"variableEnum"
. Ele reflete (no tempo de construção) o nome do campo / propriedade / parâmetro / variável e não o valor ."someEnumValue"
, enquanto você precisarianameof(SomeEnum.FooBar)
para chegar"FooBar"
.Trabalha para o nosso projeto ...
fonte
Nos meus testes,
Enum.GetName
foi mais rápido e com margem decente.ToString
Chamadas internamenteEnum.GetName
. Da fonte para o .NET 4.0, o essencial:Não posso dizer que esse seja o motivo, com certeza, mas os testes indicam que um é mais rápido que o outro. Ambas as chamadas envolvem boxe (na verdade, são chamadas de reflexão, você está basicamente recuperando nomes de campos) e pode ser lento ao seu gosto.
Se a velocidade não for perceptível, eu não me importaria e usaria,
ToString
pois oferece uma chamada muito mais limpa. Contrastecom
fonte
Enum.GetName (...)
Este é o método mais elegante para isso.
Embora eu não veja nenhum problema com a chamada
.ToString()
, ela é simplesmente mais curta.Com a nova sintaxe C # 6, você pode usar:
fonte
Tudo isso internamente acaba chamando um método chamado
InternalGetValueAsString
. A diferença entreToString
eGetName
seria a queGetName
deve verificar algumas coisas primeiro:GetType
o valor para verificar isso..ToString
não precisa se preocupar com nenhum desses problemas acima, porque é chamado em uma instância da própria classe e não em uma versão passada, portanto, devido ao fato de o.ToString
método não ter os mesmos problemas de verificação como métodos estáticos, eu concluiria que.ToString
é a maneira mais rápida de obter o valor como uma string.fonte
O melhor que posso encontrar é essa pergunta não relacionada no MSDN , que contém um trecho de código XML que responde a essa pergunta. Qualquer um desses métodos compartilha a mesma falha: eles chamam
enum.toString()
, o que não funciona corretamente ao usar o Dotfuscation . Outras preocupações parecem estar relacionadas ao boxe indireto (GetName e Format). Infelizmente, não consigo encontrar nenhuma razão de desempenho para usar qualquer uma das opções acima.Parafraseando do snippet xml ,
fonte
Enum.GetName()
Format()
é realmente apenas um invólucroGetName()
com alguma funcionalidade de formatação (ouInternalGetValueAsString()
para ser exato).ToString()
é praticamente o mesmo queFormat()
. Eu acho queGetName()
é a melhor opção, pois é totalmente óbvio o que faz para quem lê a fonte.fonte
Crio um método de extensão "Descrição" e o anexo à enumeração para que eu possa obter uma nomeação verdadeiramente amigável que inclua espaços e maiúsculas e minúsculas. Eu nunca gostei de usar o valor enum como texto exibível porque é algo que os desenvolvedores usam para criar um código mais legível. Não se destina a fins de exibição da interface do usuário. Quero poder alterar a interface do usuário sem passar e alterar as enumerações por toda parte.
fonte
Não sei qual é o método "preferido" (pergunte a 100 pessoas e obtenha 100 opiniões diferentes), mas faça o que é mais simples e o que funciona.
GetName
funciona, mas requer muito mais pressionamentos de tecla.ToString()
parece fazer o trabalho muito bem.fonte
Para os aficionados por VB:
fonte
Isso também funcionaria.
fonte
ToString()
fornece o resultado mais óbvio do ponto de vista da legibilidade, enquanto usaEnum.GetName()
requer uma análise um pouco mais mental para entender rapidamente o que está tentando fazer (a menos que você veja o padrão o tempo todo).Do ponto de vista do desempenho puro, como já fornecido na resposta do @ nawfal,
Enum.GetName()
é melhor.Se o desempenho é realmente o seu objetivo, seria ainda melhor fornecer uma pesquisa prévia (usando um Dicionário ou outro mapeamento).
Em C ++ / CLI, isso seria semelhante
Comparação usando uma enumeração de 100 itens e 1000000 iterações:
fonte
Simples: enum nomes em uma lista:
fonte