2009-03-02 9 views
10

Si tengo un método que devuelve algo, comobloques try-catch con el tipo de retorno

public DataTable ReturnSomething() 
{ 
    try 
    { 
     //logic here 
    return ds.Tables[0]; 
    } 
    catch (Exception e) 
    { 
     ErrorString=e.Message; 
    } 
} 

Esto produce error de compilación, obviamente porque catch{} bloque no devuelve nada.

Así que cuando tengo métodos con valores devueltos no uso el bloque try-catch, lo cual es una mala práctica. Si hay un error, me gustaría establecer una cadena de error para ese error. Pero luego necesito un valor de retorno también. ¿Consejo?

+0

"Así que cuando tengo métodos con valores de retorno no uso el bloque try-catch, que es una mala práctica". ¿dice quién? La mayoría de los métodos devuelven valores sin estar envueltos en bloques de prueba. –

+0

¡Golpeado por 20 segundos! De hecho, es lo que iba a decir; si hay una excepción: A MENOS QUE lo espere y pueda hacer algo útil al respecto, deje que le llame la atención a la persona que llama. –

+2

La deglución de excepciones es el verdadero problema aquí. –

Respuesta

27

tienda de su valor de retorno en una variable temporal como esto:

public DataTable ReturnSomething() 
{ 
    DataTable returnValue = null; 

    try 
    { 
     //logic here 
     returnValue = ds.Tables[0]; 
    } 
    catch (Exception e) 
    { 
     ErrorString=e.Message; 
    } 

    return returnValue; 
} 
+0

simple y hace el trabajo. –

+3

Como han notado otros, debería pensar en lanzar la excepción en lugar de establecer un ErrorString. Si desea una excepción con su propio mensaje, debe lanzar una nueva excepción, con la excepción original como excepción interna. lanza una nueva ArgumentException ("Mi mensaje", e); – Svish

+0

Estoy de acuerdo con Svish y otros; aunque intenté responder a su pregunta tal como se le preguntó, no creo que sea la mejor solución para su problema. – Simon

14

Debe levantar/lanzar la excepción en su bloque catch y manejarlo en el método de llamada.

public void invokeFaultyCode() 
{ 
    try 
    { 
     DataTable dt = ReturnSomething(); 
    } 
    catch(Exception e) 
    { 
     // Print the error message, cleanup, whatever 
    }  
} 
public DataTable ReturnSomething() throws Exception 
{ 
    try 
    { 
     //logic here 
    return ds.Tables[0]; 
    } 
    catch (Exception e) 
    { 
     ErrorString=e.Message; 
     throw; 
    } 
} 

PD: Perdón por cualquier error de sintaxis, estoy un poco oxidado en C#.

+1

Es posible que desees simplemente tirar, ya que throw e alterará la pila de excepciones. –

+0

Buen punto que tienes aquí. –

+1

Solo para tener en cuenta; Agregar 'throws' a un método es un concepto de Java que no existe en .NET. – Robula

3

Depende de su aplicación. Puede devolver null, un DataTable vacío o lo que sea adecuado según las circunstancias.

+0

Todo depende de las circunstancias. Siempre debe hacer la pregunta "¿qué significa si ocurre una excepción aquí?" en lugar de seguir la misma práctica de memoria. Parte de la razón de tener un controlador de excepción es, bueno, MANEJAR la excepción. – plinth

5

Debe encerrar a la persona que llama con una captura de prueba ... cualquier excepción que ocurra en la rutina que se llama explotará a la persona que llama y podrá atraparlos allí.

Personalmente, creo que es excesivo intentar una captura en esta rutina ya que la persona que llama debe manejar la excepción.

Para mi ejemplo, esto se codifica como sigue ...

private void DoSomething() { 
    try { 
     DataTable dt = ReturnSomething(); 
    } 
    catch (Exception ex) { 
    }  
} 

public DataTable ReturnSomething() { 
    DataTable dt = new DataTable(); 

    // logic here 
    return dt; 
} 
0

creo que el código se ejecuta en un nivel suficientemente alto de la pila de llamadas y se mezcla con el código de UI. Si este es realmente el caso, puede return null en el bloque catch. Sin embargo, si está escribiendo código reutilizable, debe refactorizarlo para que no contenga manipulación de UI y manejar la excepción en un nivel superior en la pila de llamadas.

0

Dado que está protegiendo la excepción (y no volviéndolo a lanzar) en su ejemplo, el código externo asume que todo está bien y por lo tanto debe devolver algo útil.

Si necesita detectar la excepción y hacer algo bien, pero si todavía es un error, también debería lanzarlo, o una excepción diferente, tal vez con la que acaba de capturar como InnerException.

3

Me asumir todavía se puede configurar el mensaje, y luego volver nulo o cualquiera que sea el equivalente C# es

public DataTable ReturnSomething(){ 
    try { 
     //logic here 
     return ds.Tables[0]; 
    } catch (Exception e) { 
     ErrorString=e.Message; 
     return null; 
    } 
} 
2

¿Qué tal esto:

public DataTable ReturnSomething(out string errorString) 
{ 
    errorString = string.Empty; 
    DataTable dt = new DataTable(); 
    try 
    { 
     //logic here 
    dt = ds.Tables[0]; 
    } 
    catch (Exception e) 
    { 
     errorString = e.Message; 
    } 
    return dt; 
} 
+0

¿No será un error del compilador, ya que errorString es una salida y no está garantizado que se establezca? –

+0

yeap, tienes razón, solo lo escribo en SO editor :) edición! – Canavar

+0

@ScarletGarden: hago lo mismo;] –

3

Si va a la cabeza del " no ejecute una ruta de excepción "(que no estoy recomendando necesariamente), podría seguir el enfoque TryParse que utiliza MS.

Algo así como:

private string FillDataTable(out DataTable results) 
{ 

    try 
{ 
    results = new DataTable(); //something like this; 
    return String.Empty; 
} 
catch (Exception ex) 
{ 
    results = null; 
return ex.Message; 

} 

}

6

La variable ErrorString se parece sospechosamente a una variable de código de error. La práctica recomendada es usar excepciones para pasar información de error directamente, cuando sea necesario, en lugar de almacenar cosas en códigos de error.

Está haciendo efectivamente lo mismo con su ErrorString como lo haría si solo deja que la persona que llama capte la excepción: eliminando la responsabilidad de responder a un error del método en sí. Este es un buen objetivo para tener. Pero el uso de una cadena de error no le gana nada sobre el uso de una excepción. De hecho, pierdes información de esta manera. Existe una cantidad de tipos de errores que pueden ocurrir y muchos tienen excepciones especiales asociadas a ellos, con sus propias propiedades especiales para contener información contextual sobre el error. Al guardar el mensaje en una cadena, está perdiendo esta información.

De modo que, a menos que su objetivo sea específicamente ocultar el tipo de error que está ocurriendo en la persona que llama, solo puede ganar dejando pasar la excepción.

Otra cosa a considerar es si este es realmente un escenario de error. Si es así, es muy poco probable que a su método de llamada le importe en absoluto cuál es el valor de retorno. En ese caso, no tiene nada de qué preocuparse simplemente dejando que la excepción se ejecute y no devuelva nada. Si NO es realmente un escenario de error, y la persona que llama solo va a continuar y hacer otra cosa, bueno, eso es para que la persona que llama lo decida, ¿no? Todavía no hay mucho beneficio que obtener al devolver una cadena de error y una DataTable ficticia o un nulo, antes de arrojar la excepción con toda su información de falla contextual.

0

Lo puede hacer como el código de ejemplo siguiente.

public DataTable ReturnSomething(out string OutputDesc) 
{ 
    try 
     { 
     //logic here 
     OutputDesc = string.Format("Your Successful Message Here..."); 
     return ds.Tables[0]; 
     } 
     catch (Exception e) 
     { 
     OutputDesc =e.Message; 
     return null; 
     } 

}