Busqué y no pude encontrar un duplicado. Si puede proporcionar un enlace, eliminaré esta pregunta.
Eric Weilnau
1
a veces, usar una instrucción de cambio no es la mejor práctica (cuando tienes grandes enumeraciones) puedes usar Dict <> en su lugar
Guy L
1
Si desea un mejor rendimiento, puede usar la clase descrita en este artículo codeproject.com/KB/dotnet/enum.aspx . El uso se verá así Enum <YourEnum> .ToString (yourValue) o Enum <YourEnum> .ToString ((int) yourValue)
ideafixxxer
55
La codificación para no romper la fusión de puntos es el epítome de la cola que mueve al perro. Los productores de software no están pensando: "Hagamos una aplicación genial para que dotfuscator tenga algo que hacer". Dofuscator existe para ayudar a facilitar el desarrollo de SW. Si no puede hacer eso ... ¡puede!
micahhoover
Respuestas:
125
A partir de C # 6, la mejor manera de obtener el nombre de una enumeración es el nuevo nameofoperador:
nameof(MyEnum.EnumValue);// Ouputs>"EnumValue"
Esto funciona en tiempo de compilación, con la enumeración reemplazada por la cadena en el resultado compilado, lo que a su vez significa que esta es la forma más rápida posible.
Cualquier uso de nombres de enumeración interfiere con la ofuscación de código, si considera que la ofuscación de nombres de enumeración merece la pena o es importante, esa es probablemente una pregunta completamente diferente.
Esto merece más atención. No obstante la limitación obvia, es decir, el requisito de entrada en tiempo de compilación. En mi opinión, esto debería preferirse siempre que sea posible . 'Renombrar' y 'encontrar todas las referencias' también lo tienen en cuenta, evitando potencialmente cadenas mágicas y constantes duplicadas.
Timo
1
Entonces, ¿no funcionará cuando el valor de enumeración se defina en tiempo de ejecución? Ej: MyEnum variableEnum; variableEnum = setEnumValueMethod (); nameof (variableEnum);
Maxter
1
@Maxter no, como nameof(variableEnum)será "variableEnum". Refleja (en tiempo de construcción) el nombre del campo / propiedad / parámetro / variable, no el valor .
Keith
S.M. desafortunadamente no funciona si haces esto: var someEnumvalue = SomeEnum.FooBar; nameof (someEnumvalue);
Squbly
@Sí, sí, eso volverá "someEnumValue", mientras que tendrías que nameof(SomeEnum.FooBar)hacerlo "FooBar".
Enum.GetName toma el valor como un argumento de objeto. Esto significa que el valor estará encuadrado y esto desperdiciará recursos de CPU en la asignación y en la recolección de basura. Si esto se hace mucho tiempo, Enum.GetName tendrá un rendimiento mucho menor que el almacenamiento en caché de los valores en un diccionario y la búsqueda del nombre allí.
Corrió
@Ran, ¿cuál es la solución, cuál usar en su lugar?
shaijut
Esta debería ser la respuesta
Squbly
hace que mi proyecto sea más lento toString () es más rápido.
d2k2
29
En mis pruebas, Enum.GetNamefue más rápido y con un margen decente. Internamente ToStringllamadas Enum.GetName. Desde la fuente de .NET 4.0, lo esencial:
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);}}
No puedo decir que esa sea la razón, pero las pruebas indican que una es más rápida que la otra. Ambas llamadas involucran boxeo (de hecho, son llamadas de reflexión, básicamente estás recuperando nombres de campo) y pueden ser lentas para tu gusto.
Configuración de prueba : enumeración con 8 valores, no. de iteraciones = 1000000
Resultado : Enum.GetName => 700 ms, ToString => 2000 ms
Si la velocidad no es notable, no me importaría y lo usaría, ToStringya que ofrece una llamada mucho más limpia. Contraste
Todos estos terminan internamente llamando a un método llamado InternalGetValueAsString. La diferencia entre ToStringy GetNamesería que GetNameprimero tiene que verificar algunas cosas:
El tipo que ingresó no es nulo.
El tipo que ingresó es, de hecho, una enumeración.
El valor que ingresó no es nulo.
El valor que ingresó es de un tipo que una enumeración puede usar realmente como su tipo subyacente, o del tipo de la enumeración misma. Se utiliza GetTypeen el valor para verificar esto.
.ToStringno tiene que preocuparse por ninguno de estos problemas anteriores, porque se llama en una instancia de la clase en sí, y no en una versión aprobada, por lo tanto, debido a que el .ToStringmétodo no tiene los mismos problemas de verificación Como los métodos estáticos, concluiría que .ToStringes la forma más rápida de obtener el valor como una cadena.
¿Dónde revisaste esto? ¿Cuál fue la versión de ensamblaje? Obtengo resultados muy diferentes.
nawfal
17
Lo mejor que puedo encontrar es esta pregunta no relacionada en MSDN , que contiene un fragmento XML que responde a esta pregunta. Cualquiera de estos métodos comparte el mismo defecto: llaman enum.toString(), que no funciona correctamente cuando se utiliza Dotfuscation . Otras preocupaciones parecen estar relacionadas con el boxeo indirecto (GetName y Format). Desafortunadamente, no puedo encontrar ninguna razón de rendimiento para usar cualquiera de los anteriores.
Pasar una enumeración en caja a string.Format () o cualquier otra función puede provocar que enum.ToString()se llame. Esto causará problemas al Dotfuscating. No se debe utilizar enum.ToString(), enum.GetNames(), enum.GetName(), enum.Format()o enum.Parse()para convertir una enumeración en una cadena. En su lugar, use una declaración de cambio y también internacionalice los nombres si es necesario.
Format()es realmente una envoltura GetName()con alguna funcionalidad de formato (o InternalGetValueAsString()para ser exactos). ToString()es más o menos lo mismo que Format(). Creo que GetName()es la mejor opción, ya que es totalmente obvio lo que hace para cualquiera que lea la fuente.
Creo un método de extensión "Descripción" y lo adjunto a la enumeración para que pueda obtener un nombre realmente fácil de usar que incluya espacios y mayúsculas. Nunca me ha gustado usar el valor enum como texto visualizable porque es algo que los desarrolladores usamos para crear código más legible. No está destinado a la visualización de la interfaz de usuario. Quiero poder cambiar la interfaz de usuario sin pasar y cambiar las enumeraciones por todas partes.
No sé cuál es el método "preferido" (pregunte a 100 personas y obtenga 100 opiniones diferentes), pero haga lo que sea más simple y lo que funcione. GetNamefunciona pero requiere muchas más pulsaciones de teclas. ToString()Parece que hace el trabajo muy bien.
ToString()da el resultado más obvio desde una perspectiva de legibilidad, mientras que el uso Enum.GetName()requiere un poco más de análisis mental para comprender rápidamente lo que está tratando de hacer (a menos que vea el patrón todo el tiempo).
Desde un punto de vista de rendimiento puro, como ya se proporcionó en la respuesta de @ nawfal, Enum.GetName()es mejor.
Sin embargo, si el rendimiento es realmente su objetivo, sería aún mejor proporcionar una búsqueda de antemano (utilizando un diccionario o alguna otra asignación).
En C ++ / CLI, esto se vería así
Dictionary<String^,MyEnum> mapping;for each (MyEnum field in Enum::GetValues(MyEnum::typeid)){
mapping.Add(Enum::GetName(MyEnum::typeid), field);}
Comparación utilizando una enumeración de 100 elementos y 1000000 iteraciones:
Respuestas:
A partir de C # 6, la mejor manera de obtener el nombre de una enumeración es el nuevo
nameof
operador:Esto funciona en tiempo de compilación, con la enumeración reemplazada por la cadena en el resultado compilado, lo que a su vez significa que esta es la forma más rápida posible.
Cualquier uso de nombres de enumeración interfiere con la ofuscación de código, si considera que la ofuscación de nombres de enumeración merece la pena o es importante, esa es probablemente una pregunta completamente diferente.
fuente
nameof(variableEnum)
será"variableEnum"
. Refleja (en tiempo de construcción) el nombre del campo / propiedad / parámetro / variable, no el valor ."someEnumValue"
, mientras que tendrías quenameof(SomeEnum.FooBar)
hacerlo"FooBar"
.Trabaja para nuestro proyecto ...
fuente
En mis pruebas,
Enum.GetName
fue más rápido y con un margen decente. InternamenteToString
llamadasEnum.GetName
. Desde la fuente de .NET 4.0, lo esencial:No puedo decir que esa sea la razón, pero las pruebas indican que una es más rápida que la otra. Ambas llamadas involucran boxeo (de hecho, son llamadas de reflexión, básicamente estás recuperando nombres de campo) y pueden ser lentas para tu gusto.
Si la velocidad no es notable, no me importaría y lo usaría,
ToString
ya que ofrece una llamada mucho más limpia. Contrastecon
fuente
Enum.GetName (...)
Este es el método más elegante que está destinado para ello.
Aunque no veo ningún problema con las llamadas,
.ToString()
ya que es simplemente más corto.Con la nueva sintaxis de C # 6 puede usar:
fuente
Todos estos terminan internamente llamando a un método llamado
InternalGetValueAsString
. La diferencia entreToString
yGetName
sería queGetName
primero tiene que verificar algunas cosas:GetType
en el valor para verificar esto..ToString
no tiene que preocuparse por ninguno de estos problemas anteriores, porque se llama en una instancia de la clase en sí, y no en una versión aprobada, por lo tanto, debido a que el.ToString
método no tiene los mismos problemas de verificación Como los métodos estáticos, concluiría que.ToString
es la forma más rápida de obtener el valor como una cadena.fuente
Lo mejor que puedo encontrar es esta pregunta no relacionada en MSDN , que contiene un fragmento XML que responde a esta pregunta. Cualquiera de estos métodos comparte el mismo defecto: llaman
enum.toString()
, que no funciona correctamente cuando se utiliza Dotfuscation . Otras preocupaciones parecen estar relacionadas con el boxeo indirecto (GetName y Format). Desafortunadamente, no puedo encontrar ninguna razón de rendimiento para usar cualquiera de los anteriores.Parafraseando desde el fragmento xml ,
fuente
Enum.GetName()
Format()
es realmente una envolturaGetName()
con alguna funcionalidad de formato (oInternalGetValueAsString()
para ser exactos).ToString()
es más o menos lo mismo queFormat()
. Creo queGetName()
es la mejor opción, ya que es totalmente obvio lo que hace para cualquiera que lea la fuente.fuente
Creo un método de extensión "Descripción" y lo adjunto a la enumeración para que pueda obtener un nombre realmente fácil de usar que incluya espacios y mayúsculas. Nunca me ha gustado usar el valor enum como texto visualizable porque es algo que los desarrolladores usamos para crear código más legible. No está destinado a la visualización de la interfaz de usuario. Quiero poder cambiar la interfaz de usuario sin pasar y cambiar las enumeraciones por todas partes.
fuente
No sé cuál es el método "preferido" (pregunte a 100 personas y obtenga 100 opiniones diferentes), pero haga lo que sea más simple y lo que funcione.
GetName
funciona pero requiere muchas más pulsaciones de teclas.ToString()
Parece que hace el trabajo muy bien.fuente
Para aficionados a VB:
fuente
Esto también funcionaría.
fuente
ToString()
da el resultado más obvio desde una perspectiva de legibilidad, mientras que el usoEnum.GetName()
requiere un poco más de análisis mental para comprender rápidamente lo que está tratando de hacer (a menos que vea el patrón todo el tiempo).Desde un punto de vista de rendimiento puro, como ya se proporcionó en la respuesta de @ nawfal,
Enum.GetName()
es mejor.Sin embargo, si el rendimiento es realmente su objetivo, sería aún mejor proporcionar una búsqueda de antemano (utilizando un diccionario o alguna otra asignación).
En C ++ / CLI, esto se vería así
Comparación utilizando una enumeración de 100 elementos y 1000000 iteraciones:
fuente
Simple: enumerar nombres en una lista:
fuente