Quelle est la méthode préférée pour convertir une énumération en chaîne dans .NET 3.5?
- Enum.GetName
- Enum.Format
- ToString
Pourquoi devrais-je préférer l'un d'entre eux aux autres? Est-ce que l'un est plus performant?
Quelle est la méthode préférée pour convertir une énumération en chaîne dans .NET 3.5?
Pourquoi devrais-je préférer l'un d'entre eux aux autres? Est-ce que l'un est plus performant?
Réponses:
Depuis C # 6, la meilleure façon d'obtenir le nom d'une énumération est le nouvel nameof
opérateur:
nameof(MyEnum.EnumValue);
// Ouputs
> "EnumValue"
Cela fonctionne au moment de la compilation, l'énumération étant remplacée par la chaîne dans le résultat compilé, ce qui signifie que c'est le moyen le plus rapide possible.
Toute utilisation de noms enum interfère avec l'obscurcissement du code, si vous considérez que l'obfuscation des noms enum vaut la peine ou est importante - c'est probablement une toute autre question.
nameof(variableEnum)
sera "variableEnum"
. Il reflète (au moment de la construction) le nom du champ / propriété / paramètre / variable et non la valeur .
"someEnumValue"
, alors que vous auriez besoin nameof(SomeEnum.FooBar)
de l'obtenir "FooBar"
.
Fonctionne pour notre projet ...
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);
}
Dans mes tests, Enum.GetName
c'était plus rapide et avec une marge décente. ToString
Appels en interne Enum.GetName
. De la source pour .NET 4.0, l'essentiel:
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);
}
}
Je ne peux pas dire que c'est la raison avec certitude, mais les tests indiquent que l'un est plus rapide que l'autre. Les deux appels impliquent de la boxe (en fait, ce sont des appels de réflexion, vous récupérez essentiellement les noms de champs) et peuvent être lents à votre goût.
Configuration du test : enum avec 8 valeurs, non. d'itérations = 1000000
Résultat : Enum.GetName => 700 ms, ToString => 2000 ms
Si la vitesse n'est pas perceptible, je ne m'en soucierais pas et l'utiliserais ToString
car elle offre un appel beaucoup plus propre. Contraste
Enum.GetName(typeof(Bla), value)
avec
value.ToString()
C'est la méthode la plus élégante qui lui soit destinée.
var enumValueString = Enum.GetName(typeof (MyEnum), MyEnum.MyValue);
Bien que je ne vois aucun problème avec l'appel .ToString()
car il est simplement plus court.
var enumValueString = MyEnum.MyValue.ToString();
Avec la nouvelle syntaxe C # 6, vous pouvez utiliser:
nameof(MyEnum.MyValue)
Tous ces éléments finissent par appeler en interne une méthode appelée InternalGetValueAsString
. La différence entre ToString
et GetName
serait qu'il GetName
faut d'abord vérifier quelques choses:
GetType
la valeur pour vérifier cela..ToString
n'a pas à s'inquiéter de l'un des problèmes ci-dessus, car il est appelé sur une instance de la classe elle-même, et non sur une version passée, par conséquent, en raison du fait que la .ToString
méthode n'a pas les mêmes problèmes de vérification en tant que méthodes statiques, je conclurais que .ToString
c'est le moyen le plus rapide d'obtenir la valeur sous forme de chaîne.
Le mieux que je puisse trouver est cette question sans rapport sur MSDN , qui contient un extrait de code XML qui répond à cette question. Chacune de ces méthodes partage le même défaut: elles appellent enum.toString()
, ce qui ne fonctionne pas correctement lors de l'utilisation de Dotfuscation . D'autres préoccupations semblent concerner la boxe indirecte (GetName et Format). Malheureusement, je ne trouve aucune raison de performances pour utiliser l'un des éléments ci-dessus.
Paraphrasant de l' extrait de code XML ,
Passer une énumération encadrée à string.Format () ou à toute autre fonction peut entraîner l'
enum.ToString()
appel. Cela posera des problèmes lors de Dotfuscating. Vous ne devriez pas utiliserenum.ToString()
,enum.GetNames()
,enum.GetName()
,enum.Format()
ouenum.Parse()
pour convertir un ENUM en une chaîne. Au lieu de cela, utilisez une instruction switch et internationalisez également les noms si nécessaire.
Enum.GetName()
Format()
est vraiment juste un wrapper GetName()
avec des fonctionnalités de formatage (ou InternalGetValueAsString()
pour être exact). ToString()
est à peu près le même que Format()
. Je pense que GetName()
c'est la meilleure option car il est tout à fait évident ce que cela fait pour quiconque lit la source.
Je crée une méthode d'extension "Description" et l'attache à l'énumération afin que je puisse obtenir une dénomination vraiment conviviale qui inclut des espaces et des casse. Je n'ai jamais aimé utiliser la valeur enum elle-même comme texte affichable car c'est quelque chose que les développeurs utilisent pour créer un code plus lisible. Il n'est pas destiné à des fins d'affichage de l'interface utilisateur. Je veux pouvoir changer l'interface utilisateur sans passer par et changer les énumérations partout.
Je ne sais pas quelle est la méthode "préférée" (demandez à 100 personnes et obtenez 100 opinions différentes) mais faites ce qui est le plus simple et ce qui fonctionne. GetName
fonctionne mais nécessite beaucoup plus de frappes. ToString()
semble très bien faire le travail.
ToString()
donne le résultat le plus évident du point de vue de la lisibilité, tandis que l'utilisation Enum.GetName()
nécessite un peu plus d'analyse mentale pour comprendre rapidement ce qu'il essaie de faire (à moins que vous ne voyiez le modèle tout le temps).
Du point de vue de la performance pure, comme déjà indiqué dans la réponse de @ nawfal, Enum.GetName()
c'est mieux.
Si la performance est vraiment votre objectif, il serait encore mieux de fournir une recherche au préalable (en utilisant un dictionnaire ou un autre mappage).
En C ++ / CLI, cela ressemblerait à
Dictionary<String^, MyEnum> mapping;
for each (MyEnum field in Enum::GetValues(MyEnum::typeid))
{
mapping.Add(Enum::GetName(MyEnum::typeid), field);
}
Comparaison utilisant une énumération de 100 éléments et 1000000 itérations:
Enum.GetName: ~ 800ms
.ToString (): ~ 1600ms Mappage du
dictionnaire: ~ 250ms