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 nameof
operador:
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.GetName
foi mais rápido e com margem decente. ToString
Chamadas 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, ToString
pois 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 ToString
e GetName
seria a que GetName
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.
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. GetName
funciona, 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