2010-04-22 21 views
9

Tengo una consulta de inserción que devuelve un int. En función de ese int, puedo lanzar una excepción. ¿Es apropiado hacerlo dentro de una declaración de cambio?Puede/Debe arrojar excepciones en una instrucción C# switch?

switch (result) 
     { 

      case D_USER_NOT_FOUND: 
       throw new ClientException(string.Format("D User Name: {0} , was not found.", dTbx.Text)); 
      case C_USER_NOT_FOUND: 
       throw new ClientException(string.Format("C User Name: {0} , was not found.", cTbx.Text)); 
      case D_USER_ALREADY_MAPPED: 
       throw new ClientException(string.Format("D User Name: {0} , is already mapped.", dTbx.Text)); 
      case C_USER_ALREADY_MAPPED: 
       throw new ClientException(string.Format("C User Name: {0} , is already mapped.", cTbx.Text)); 
      default: 

       break; 
     } 

Normalmente agrego declaraciones de interrupción a los interruptores, pero no se verán afectados. ¿Es este un mal diseño? Por favor comparte cualquier opinión/sugerencia conmigo.

Gracias, ~ ck en San Diego

+2

Parece que está tratando de asignar códigos de retorno a las excepciones. Tu intención es clara, así que diría que esta solución está bien. –

Respuesta

3

yo realmente no está de acuerdo con las convenciones de denominación de variables;), pero no veo por qué lo que hizo no sería apropiado. Parece una forma bastante elegante de traducir un error de un medio a otro.

Supongo que su "consulta de inserción" es una forma de proceso almacenado.

+0

Sí señor, tiene razón. Gracias. – Hcabnettek

0

Creo que esto está bien. Parece que está mapeando un código de retorno a una excepción, usando una declaración de cambio. Mientras no haya demasiados casos, esto no es un problema.

1

Si es posible, probablemente sería mejor tirar donde sea que se establezca el resultado fallido, de lo contrario terminará teniendo que hacer tanto la comprobación de resultados como el lanzamiento. Pero podría no ser posible, por supuesto.

Además, convertiría sus cadenas de error en recursos o constantes con marcadores de posición para que no tenga que cambiar varios lugares si desea cambiar la redacción.

4

No hay problema ... ¿por qué sería este un mal diseño?

Como alternativa, dado que el tipo de excepción es el mismo en todos case s, puede construir una tabla de búsqueda para los mensajes de error. Eso te ahorraría algo de duplicación de código. Por ejemplo:

static private Dictionary<int, string> errorMessages; 
static 
{ 
    // create and fill the Dictionary 
} 

// meanwhile, elsewhere in the code... 
if (result is not ok) { 
    throw new ClientException(string.Format(errorMessages[result], cTbx.Text, dTbx.Text)); 
} 

En los propios mensajes, puede seleccionar el parámetro adecuado con {0}, {1}, etc.

0

No hay nada malo con el enfoque que está tomando. Las instrucciones de cambio son mucho más fáciles de leer que las declaraciones de si/entonces (y potencialmente más rápidas también). La otra cosa que podría hacer es cargar las excepciones posibles en un

Dictionary<Result_Type, Exception> 

y extraer la excepción desde allí. Si tiene muchas instrucciones de conmutación, esto haría que el código sea más compacto (y puede agregarlo y eliminarlo en tiempo de ejecución si es necesario).

+0

Un diccionario podría ser bueno, pero tendría que ser un 'Diccionario ' o algo así como 'Diccionario ', o 'Diccionario ', con una definición adecuada clase de fábrica de excepción (y la interfaz, si corresponde) definida en alguna parte. Lanzar un objeto Exception existente como mínimo destruirá el seguimiento de la pila. Si dos subprocesos encuentran el mismo tipo de excepción simultáneamente, compartir un objeto de excepción entre ellos podría hacer que el manejador de un subproceso vea el rastro de pila del otro subproceso. – supercat

+0

Sí, no es el mejor ejemplo de cómo usar un diccionario para eso. En todo caso, probablemente deba almacenar el tipo de excepción, y no la propia excepción en sí misma. – kemiller2002

+0

Desafortunadamente, almacenar el tipo de excepción no es útil para mucho, ya que a menos que uno use Reflection (una preposición un tanto dudosa en el contexto de una excepción) no hay una forma general de generar un excepción de un tipo de excepción. ese tipo. – supercat

12

¿Por qué no?

De The C# Programming Language, Third Ed. por Anders Hejlsberg et al, página 362:

La lista de instrucciones de una sección de conmutación termina típicamente en una, goto case, o goto default declaración break, pero se permite cualquier construcción que reproduce el punto final de la lista de instrucciones inalcanzable . [...] Del mismo modo, una declaración throw o return siempre transfiere el control a otro lugar y nunca alcanza su punto final.Así, el siguiente ejemplo es válido:

switch(i) { 
case 0: 
    while(true) F(); 
case 1: 
    throw new ArgumentException(); 
case 2: 
    return; 
} 
0

no veo ningún problema con el uso de un interruptor en su caso.

La consideración más importante debe ser si las excepciones son apropiadas. Generalmente, las excepciones deben usarse solo cuando surge una situación que está fuera de los límites del comportamiento esperado. Las excepciones no se deben usar como lógica de flujo de programa. En su caso, probablemente esté bien usarlos según el código que veo.

0

Tal vez estoy de acuerdo entre todas las respuestas aquí ..

En lugar de tener que cambiar en el código, preferiría pasar en el result a la clase ClientException & deje que se decida qué cadena se tiene que mostrar en lugar de tener un interruptor feo todo el lugar para crear varios mensajes

Mi código se vería así:

throw new ClientException(result, cTbx.Text); 

por lo tanto, incluso si se puede tirar errores en switch...case, puede evitarlo todo es mi opinión

+1

En ese momento, el constructor ClientException tendría la misma lógica de conmutación, pero debería tener descansos. – Yishai

+0

o an si ... else :) – Sunny

+0

Bajé la votación porque esta "solución" simplemente cambia el problema. Esto no hace ninguna diferencia real. –

Cuestiones relacionadas