J'ai cherché et je n'ai pas trouvé de doublon. Si vous pouvez fournir un lien, je supprimerai cette question.
Eric Weilnau
1
parfois, l'utilisation d'une instruction switch n'est pas la meilleure pratique (lorsque vous avez de grandes énumérations), vous pouvez utiliser Dict <> à la place
Guy L
1
Si vous voulez de meilleures performances, vous pouvez utiliser la classe décrite dans cet article codeproject.com/KB/dotnet/enum.aspx . L'utilisation ressemblera à ceci Enum <YourEnum> .ToString (yourValue) ou Enum <YourEnum> .ToString ((int) yourValue)
ideafixxxer
5
Coder pour ne pas casser la dotfuscation est la quintessence de la queue qui remue le chien. Les producteurs de logiciels ne pensent pas: "Faisons une excellente application pour que dotfuscator ait quelque chose à faire." Dofuscator existe pour faciliter le développement de logiciels. S'il ne peut pas faire ça ... peut-il!
micahhoover
Réponses:
127
Depuis C # 6, la meilleure façon d'obtenir le nom d'une énumération est le nouvel nameofopé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.
Cela mérite plus d'attention. Nonobstant la limitation évidente, c'est-à-dire l'exigence d'une entrée au moment de la compilation. À mon avis, cela devrait être préféré dans la mesure du possible . «Renommer» et «trouver toutes les références» en tiennent également compte, évitant potentiellement les chaînes magiques et les constantes en double.
Timo
1
Donc, je suppose que cela ne fonctionnera pas lorsque la valeur enum est définie au moment de l'exécution? Ex: MyEnum variableEnum; variableEnum = setEnumValueMethod (); nameof (variableEnum);
Maxter
1
@ Maxter non, comme ce 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 .
Keith
vous. malheureusement ne fonctionne pas si vous faites ceci: var someEnumvalue = SomeEnum.FooBar; nameof (someEnumvalue);
Squably
1
@Squiblement oui, cela reviendra "someEnumValue", alors que vous auriez besoin nameof(SomeEnum.FooBar)de l'obtenir "FooBar".
Enum.GetName prend la valeur comme argument d'objet. Cela signifie que la valeur sera encadrée et cela gaspillera des ressources CPU sur l'allocation et sur le ramasse-miettes. Si cela est fait beaucoup de temps, Enum.GetName aura un débit beaucoup plus faible que la mise en cache des valeurs dans un dictionnaire et la recherche du nom là-bas.
Ran
@Ran alors quelle est la solution, laquelle utiliser à la place?
shaijut
Cela devrait être la réponse
Squably
rend mon projet plus lent. toString () est plus rapide.
d2k2
29
Dans mes tests, Enum.GetNamec'était plus rapide et avec une marge décente. ToStringAppels en interne Enum.GetName. De la source pour .NET 4.0, l'essentiel:
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);}}
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 ToStringcar elle offre un appel beaucoup plus propre. Contraste
Tous ces éléments finissent par appeler en interne une méthode appelée InternalGetValueAsString. La différence entre ToStringet GetNameserait qu'il GetNamefaut d'abord vérifier quelques choses:
Le type que vous avez entré n'est pas nul.
Le type que vous avez entré est en fait une énumération.
La valeur que vous avez transmise n'est pas nulle.
La valeur que vous avez transmise est d'un type qu'une énumération peut réellement utiliser comme type sous-jacent, ou du type de l'énumération elle-même. Il utilise GetTypela valeur pour vérifier cela.
.ToStringn'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 .ToStringméthode n'a pas les mêmes problèmes de vérification en tant que méthodes statiques, je conclurais que .ToStringc'est le moyen le plus rapide d'obtenir la valeur sous forme de chaîne.
où avez-vous vérifié ces derniers? Quelle était la version d'assemblage? J'obtiens des résultats très différents.
nawfal
17
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.
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 utiliser enum.ToString(), enum.GetNames(), enum.GetName(), enum.Format()ou enum.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.
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. GetNamefonctionne 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:
Réponses:
Depuis C # 6, la meilleure façon d'obtenir le nom d'une énumération est le nouvel
nameof
opérateur: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.
la source
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 besoinnameof(SomeEnum.FooBar)
de l'obtenir"FooBar"
.Fonctionne pour notre projet ...
la source
Dans mes tests,
Enum.GetName
c'était plus rapide et avec une marge décente.ToString
Appels en interneEnum.GetName
. De la source pour .NET 4.0, l'essentiel: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.
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. Contrasteavec
la source
Énumération.GetName (...)
C'est la méthode la plus élégante qui lui soit destinée.
Bien que je ne vois aucun problème avec l'appel
.ToString()
car il est simplement plus court.Avec la nouvelle syntaxe C # 6, vous pouvez utiliser:
la source
Tous ces éléments finissent par appeler en interne une méthode appelée
InternalGetValueAsString
. La différence entreToString
etGetName
serait qu'ilGetName
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.la source
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 ,
la source
Enum.GetName()
Format()
est vraiment juste un wrapperGetName()
avec des fonctionnalités de formatage (ouInternalGetValueAsString()
pour être exact).ToString()
est à peu près le même queFormat()
. Je pense queGetName()
c'est la meilleure option car il est tout à fait évident ce que cela fait pour quiconque lit la source.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.
la source
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.la source
Pour les aficionados de VB:
la source
Cela fonctionnerait aussi.
la source
ToString()
donne le résultat le plus évident du point de vue de la lisibilité, tandis que l'utilisationEnum.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 à
Comparaison utilisant une énumération de 100 éléments et 1000000 itérations:
la source
Simple: énumérer les noms dans une liste:
la source