Qual é a maneira preferida de converter um Enum em uma String no .NET 3.5?
- Enum.GetName
- Enum.Format
- Para sequenciar
Por que devo preferir um deles ao invés dos outros? Alguém tem um desempenho melhor?
Qual é a maneira preferida de converter um Enum em uma String no .NET 3.5?
Por que devo preferir um deles ao invés dos outros? Alguém tem um desempenho melhor?
Respostas:
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.
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ê precisaria nameof(SomeEnum.FooBar)para chegar "FooBar".
Trabalha para o nosso projeto ...
public static String convertToString(this Enum eff)
{
return Enum.GetName(eff.GetType(), eff);
}
public static EnumType converToEnum<EnumType>(this String enumValue)
{
return (EnumType) Enum.Parse(typeof(EnumType), enumValue);
}
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:
public override String ToString()
{
return Enum.InternalFormat((RuntimeType)GetType(), GetValue());
}
private static String InternalFormat(RuntimeType eT, Object value)
{
if (!eT.IsDefined(typeof(System.FlagsAttribute), false))
{
String retval = GetName(eT, value); //<== the one
if (retval == null)
return value.ToString();
else
return retval;
}
else
{
return InternalFlagsFormat(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
Enum.GetName(typeof(Bla), value)
com
value.ToString()
Este é o método mais elegante para isso.
var enumValueString = Enum.GetName(typeof (MyEnum), MyEnum.MyValue);
Embora eu não veja nenhum problema com a chamada .ToString(), ela é simplesmente mais curta.
var enumValueString = MyEnum.MyValue.ToString();
Com a nova sintaxe C # 6, você pode usar:
nameof(MyEnum.MyValue)
Tudo isso internamente acaba chamando um método chamado InternalGetValueAsString. A diferença entre ToStringe GetNameseria a que GetNamedeve verificar algumas coisas primeiro:
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.
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 ,
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 usarenum.ToString(),enum.GetNames(),enum.GetName(),enum.Format()ouenum.Parse()para converter um enum para uma string. Em vez disso, use uma instrução switch e internacionalize os nomes, se necessário.
Enum.GetName()
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:
Enum.GetName: ~
800ms .ToString (): ~ 1600ms
Mapeamento de dicionário: ~ 250ms