Pregunta

Si tengo un método que devuelve algo, como

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

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

Entonces, cuando tengo métodos con valores de retorno 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 también necesito un valor de retorno. ¿Consejo?

¿Fue útil?

Solución

Almacene su valor de retorno en una variable temporal como esta:

public DataTable ReturnSomething()
{
    DataTable returnValue = null;

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

    return returnValue;
}

Otros consejos

Debes aumentar / lanzar la excepción en tu bloque catch y manejarla 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 #.

Debería envolver a la persona que llama con un retén de prueba ... cualquier excepción que ocurra en la rutina a la que se llama se propagará a la persona que llama y usted podrá encontrarla allí.

Personalmente, creo que es excesivo tener un retén de prueba en esta rutina, ya que debería hacer que la persona que llama maneje la excepción.

Para mi ejemplo, esto se codificaría de la siguiente manera ...

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

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

    // logic here
    return dt;
}

La variable ErrorString se ve sospechosamente como una variable de código de error. La práctica recomendada es usar excepciones para pasar la información de error directamente, cuando sea necesario, en lugar de almacenarlos en códigos de error.

Efectivamente, está haciendo lo mismo con su ErrorString como lo haría si dejara que la persona que llama detecte la excepción: eliminando la responsabilidad de responder a un error del propio método. Este es un buen objetivo para tener. Pero el uso de una cadena de error no le otorga nada sobre el uso de una excepción. De hecho, pierdes información de esta manera. Hay muchos tipos de errores que pueden ocurrir, y muchos tienen excepciones especiales asociadas, con sus propias propiedades especiales para mantener información contextual sobre la falla. Al guardar el mensaje en una cadena, está perdiendo esta información.

Por lo tanto, a menos que su objetivo sea ocultar específicamente el tipo de error que está ocurriendo a la persona que llama, solo puede obtenerlo 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 su método de llamada cuide lo que sea el valor de retorno. En cuyo caso, no tiene nada de qué preocuparse al dejar ir la excepción y no devolver nada. Si NO es realmente un escenario de error, y la persona que llama simplemente continuará y hará otra cosa, bueno, eso es para que la persona que llama decida, ¿verdad? Todavía no hay mucho beneficio que obtener devolviendo una cadena de error y un DataTable ficticio o un nulo, sobrepasando la excepción con toda su información de falla contextual.

Si va a encabezar la ruta " no lanzar una ruta de excepción " (que no estoy necesariamente recomendando), puede seguir el enfoque de TryParse que usa MS.

Algo 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;

}

}

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

Supondría que aún puedes configurar el mensaje, luego devolver el valor nulo o lo que sea el equivalente de c #

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

¿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;
}

Ya que está ejecutando la excepción (y no la lanza de nuevo) en su ejemplo, el código externo asume que todo está bien y por lo tanto debería devolver algo útil.

Si necesitas capturar la excepción allí y hacer algo que está bien, pero si aún es un caso de error, también debes lanzarlo, o una excepción diferente, tal vez con la que acabas de capturar como InnerException.

Creo que su código se está ejecutando a un nivel suficientemente alto de la pila de llamadas y está mezclado con el código UI. Si este es realmente el caso, podría devolver nulo en el bloque catch. Sin embargo, si está escribiendo un código reutilizable, debe refactorizarlo para que no contenga manipulación de la IU y manejar la excepción en un nivel superior en la pila de llamadas.

Puedes hacerlo como el código de muestra a continuación.

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;
      }

}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top