2009-08-13 14 views
30

he definido un C# enumeración como¿Cómo puedo usar el valor de cadena de un valor enum de C# en una declaración de caso?

public enum ORDER 
{ 
    ... 
    unknown, 
    partial01, 
    partial12, 
    partial23, 
} 

y puede utilizar su valor como una cadena como en:

  string ss = ORDER.partial01.ToString(); 

Sin embargo cuando trato de usarlo en un comunicado caso de que falla al compilar:

string value = ... 
switch (value) 
{ 
    case null: 
     break; 
    case "s": 
     // OK 
     break; 
    case ORDER.partial01.ToString(): 
     // compiler throws "a constant value is expected" 

     break; 
    ... 

Pensé que los enum eran constantes. ¿Cómo puedo evitar esto?

(I no puede analizar el valor en un enum como algunos de los valores están fuera del rango)

Respuesta

21

La enumeración es una constante, sino el resultado de .ToString() no lo es. En lo que respecta al compilador, es un valor dinámico. Probablemente necesite convertir su caja de conmutadores en una serie de sentencias if/else

41

Convierta la cadena de su conmutador en un valor enum.

(ORDER)Enum.Parse(typeof(ORDER), value, true); 
+0

que no va a manejar la comparación nula, pero que caso extremo podría ser manejado fuera de la declaración de caso. –

+0

valor de cadena = nulo; // "partial01"; ¿ORDEN? orden = valor == nulo? null: (¿ORDER?) Enum.Parse (typeof (ORDER), value, true); –

2

valores de enumeración son constantes, sino que están tratando de utilizar los resultados de un método (ORDER.partial01.ToString()), no es una constante.

La mejor opción, en mi opinión, sería simplemente cambiar esto a usar sentencias if/else if/else, en lugar de un modificador. Esto te permitiría usar la lógica que estás deseando.

Alternativamente, si cambia su cadena al valor enum, puede activar los valores enum directamente. Sin embargo, no puede activar el enum + null + otras cadenas en un solo interruptor.

+0

Puede activar nulo si usa ORDER? ... no cuerdas, sin embargo. –

2

No podría usted acaba de decir en lugar

case "partial01": 

?

+2

Entonces sería difícil de codificar y duplicar los valores en el Enum. Eso podría ponerse feo bastante rápido. – MrGreggles

1

enumeraciones son constantes pero ToString() es una función que devuelve un valor. en función de la instancia del objeto enum al que se está llamando.

Es decir las dos afirmaciones:

ORDER.partial01.ToString() 
ORDER.partial02.ToString() 

llama a la misma función, pero devuelve dos valores diferentes, por lo que la llamada a la función .ToString() es en si mismo no es un valor constante.

1

Esto no es un valor estático en lo que se refiere al compilador, ya que se trata de una llamada de función:

ORDER.partial01.ToString() 

Por lo tanto, no se puede utilizar como una comparación en un comunicado caso. Sin embargo, simplemente puede hacer esto:

case "partial01" 

Eso funcionaría, ya que el valor enum y la cadena son idénticos.

28

Como alternativa al uso de if .. else, primero puede convertir su cadena a enum.Es probable que no tendría mucho sentido si el número de opciones es pequeña, aunque:

if (Enum.IsDefined(typeof(ORDER), value)) 
{ 
    switch ((ORDER)Enum.Parse(typeof(ORDER), value) 
    { 
     case ORDER.partial01: 
      // ... 
      break; 
     case ORDER.partial12: 
      // etc 
    } 
} 
else 
{ 
    // Handle values not in enum here if needed 
} 

* suspiro * Si sólo había incorporado un T Enum.Parse<T>(string value), y una versión TryParse :)

+4

y el es un 'Enum.TRyParse (valor de cadena, salida T resultado)' http://msdn.microsoft.com/en-us/library/dd783499.aspx (es v4.5) por lo que no estaba disponible en el momento de escribir) –

+0

interruptor ((PEDIDO) Enum.Parse (typeof (ORDER), value) pierde un final ")" – Enrico

9

te diseñó esto como una enumeración por una razón, pero en realidad no estás usándolo como una enumeración. ¿Por qué toma el valor enum y lo convierte en una cadena para luego usarlo en vez de simplemente usar la enumeración?

Dijiste que no puedes analizar esto en una enumeración porque algunos de los valores están fuera del rango de enumeración. La pregunta a hacer entonces es: "¿Por qué?" ¿Cuál es el punto de tener la enumeración si está permitiendo valores que no están definidos? ¿Qué es lo que quieres que suceda cuando obtienes un valor que no está definido? Si es lo mismo para cualquier valor indefinido, entonces puede usar el caso predeterminado. Si no es así, puede incluir casos adicionales que coincidan con la representación numérica.

Si realmente recuperas las cuerdas, entonces probablemente no quieras usar una enumeración. En su lugar, desea crear una clase pública estática que contenga constantes de cadenas públicas, que luego puede usar en su conmutador. El truco aquí es que la evaluación se hará de una manera sensible a las mayúsculas y minúsculas.

public static class Order 
{ 
    public const string Unknown = "Unknown"; 
    public const string Partial01 = "Partial01"; 
    public const string Partial12 = "Partial12"; 
    public const string Partial23 = "Partial23"; 
} 

string value = Order.Partial01 
switch (value) 
{ 
    case Order.Partial01: 
     break; 

    default: 
     // Code you might want to run in case you are 
     // given a value that doesn't match. 
     break; 
} 

(Usted también puede limpiar su carcasa.)

+0

hay momentos en que solo se examinan los valores enum y otras veces cuando se trata de una gama más amplia de valores . Estoy de acuerdo en que probablemente sea un diseño desordenado y que pueda desaparecer más tarde. –

+0

@ peter.murray.rust: ¿Qué tipo de valor obtiene en realidad?¿Siempre obtienes el valor como una cadena o es numérico? Si es numérico, mantenga la enumeración, active el valor ** como una enumeración ** y tenga un caso predeterminado u otros casos etiquetados que coincidan con los valores "adicionales" para realizar el trabajo adecuado. Si se trata de una cadena, vaya con el enfoque que mostré y tenga una clase estática que contenga las representaciones de la cadena. Todavía puede agregar otros casos etiquetados que coincidan con los valores "adicionales". En pocas palabras, una enumeración realmente solo es útil si desea dar a los valores numéricos nombres "amigables" o significativos. –

4

Como se indica Thorarin, si su estado switch sólo puede contener enum casos, convertir su string a un enum primero. Al menos a partir de NET Framework 4, puede utilizar el método Enum.TryParse()<TEnum> como se define here y hacer algo como:

ORDER orderEnum = ORDER.unknown; 
Enum.TryParse<ORDER>(value, out orderEnum); 

switch (orderEnum) 
{ 
    case ORDER.unknown: 
     // perhaps do something to deal with cases not matching 
     // to known enum values, based on the string value 
     break; 
    case ORDER.partial01: 
    case ORDER.partial12: 
    case ORDER.partial23: 
     // map value to known cases, etc. 
     break; 
} 
27

Puesto que C# 6, se puede utilizar: case nameof(SomeEnum.SomeValue):

nombredel se evalúa en tiempo de compilación, simplemente a una cadena que coincida con el nombre (no calificado) de la variable, tipo o miembro dado. Naturalmente, cambia de inmediato si alguna vez cambia el nombre de la opción enum.

+1

Excelente. Quería usar el valor de cadena de enum en tiempo de compilación (en un atributo) y esto lo resolvió para mí. – dubbreak

0

simplemente se puede definir una variable global

static ORDER orderstr; 

ahora se puede establecer el valor de orderstr en cualquier lugar de la página

public enum ORDER 
{ 
    unknown, 
    partial01, 
    partial12, 
    partial23, 
} 

switch (orderstr) 
{ 
    case Order.Partial01: 
     break; 
    default: 
     break; 
} 
Cuestiones relacionadas