Pregunta

En algunos códigos de Delphi 7 que estoy manteniendo, he notado muchas instancias de lo siguiente:

with ADOQuery1 do begin
  // .. fill out sql.text, etc
  try
    execSQL;
  except
    raise;
  end;
end;

Me parece que estos bloques de prueba podrían eliminarse, ya que no hacen nada. Sin embargo, desconfío de los posibles efectos secundarios sutiles ...

¿Alguien puede pensar en alguna instancia en la que estos bloques realmente podrían hacer algo que no sucedería sin ellos allí?

¿Fue útil?

Solución

En este contexto, la operación de aumento no tiene ningún efecto y debe eliminarse porque simplemente vuelve a generar la excepción que el bloque de excepción acaba de detectar. raise normalmente se usa para transferir el control al final del bloque cuando no hay un manejo de errores apropiado disponible. A continuación, manejamos la excepción personalizada, pero cualquier otra excepción debe manejarse en otro lugar.

try
  someOperation;
except
  on e: ECustomException do
    SomeCustomHandelr;
  else
     begin
       // the raise is only useful to rethrow the exception to an encompasing 
       // handler.  In this case after I have called my logger code. as Rob
       // mentioned this can be omitted if you arent handling anything because
       // the compiler will simply jump you to the next block if there is no
       // else.
       LogUnexpectedException('some operation failed',e);
       raise;
     end;
end;

Tenga cuidado de que exista una forma similar sin el " raise " eso sí tiene el efecto secundario de comer / ocultar cualquier excepción. prácticas de desarrolladores muy inescrupulosos que, con suerte, han pasado a posiciones en la competencia.

with ADOQuery1 do begin  
  // .. fill out sql.text, etc  
  try    
    execSQL; 
  except
    // no handler so this just eats any "errors"    
  end;

Otros consejos

Eliminar el código excepto en el fragmento de código anterior no hará ninguna diferencia. Puede (y creo que debería ya que está reduciendo la legibilidad) eliminarlo.

Bien, realmente dos preguntas aquí.

Primero, es significativo: si execSQL arroja una excepción, es capturado por el bloque try y reenviado a la excepción. Luego, el aumento lo reenvía al siguiente bloque más alto.

Segundo, ¿es útil ? Probablemente no. Es casi seguro que es el resultado de una de tres cosas:

  1. Alguien con cabello puntiagudo escribió un estándar de codificación que decía "todas las operaciones que pueden lanzar una excepción deben estar en un bloque de prueba".
  2. Alguien tenía la intención de regresar y convertir las excepciones hechas por la declaración execSQL en alguna otra excepción más significativa.
  3. Alguien nuevo no sabía que lo que habían escrito era isomorfo para dejar que el entorno del útero se preocupara por la excepción, por lo que pensó que debía reenviarlo.

Puede que haya respondido un poco rápido, mira al final ...
Como es, no sirve para la aplicación .
Período!

Ahora en el " por qué " lado. Puede ser para estandarizar el manejo de excepciones si hay / estaba / estará / está en otros lugares / algún tipo de código de registro insertado antes del aumento:

  try
    execSQL;
  except
    // Log Exception..
    on E: Exception do
    begin
      LogTrace(Format('%s: Exception Message[%s]',[methodname, E.Message]));
      raise;
    end;
  end;

o para el código de limpieza:

  try
    execSQL;
  except
    //some FreeAndNil..
    raise;
  end;

Actualización : Habría 1 caso en el que vería algún uso tal como es ...
... para poder poner un Punto de interrupción en la línea raise , para tener la oportunidad de ver lo que sucede en el contexto en ese bloque de código.

Este código no hace nada más que permitir que el programador original coloque un punto de interrupción en el 'Elevar' y ver la excepción más cerca en la fuente de su posible causa. En ese sentido, es una técnica de depuración perfectamente razonable.

En realidad, debería publicar esto como comentario a las respuestas de François, pero no sé si es posible insertar código formateado allí :( Así que estoy publicando esto como respuesta.

2mghie:

  
    
      

El segundo es completamente unidiomático, uno usaría finalmente en su lugar.

    
  

No, " finalmente " limpiará el objeto siempre. " Excepto " - Solo a excepción. Considere el caso de la función, que crea, llena y devuelve un objeto:

function CreateObj: TSomeObj;
begin
  Result := TSomeObj.Create;
  try
    ... // do something with Result: load data, fill props, etc.
  except
    FreeAndNil(Result); // oops: bad things happened. Free object to avoid leak.
    raise;
  end;
end;

Si pones " finalmente " allí: la función devolverá nil siempre. Si omite " intente " bloquear en absoluto: habrá una fuga de recursos en caso de excepción en " ... " ;.

P.S. Por supuesto, puede usar " finalmente " y marque ExceptObj, pero ... ¿no es feo?

El título contiene una pregunta bastante amplia, mientras que su explicación da un ejemplo más específico. Por lo tanto, mi respuesta a la pregunta sobre cómo procede del ejemplo, sin duda puede agregar algo útil a lo que ya se ha dicho aquí.

Pero, quizás Blorgbeard realmente quiere saber si es en absoluto significativo para intentar ... excepto raise; fin . En Delphi 7, si recuerdo correctamente, Exit activaría la parte finalmente de un bloque try-finally (como si fuera algún tipo de excepción). Alguien podría considerar dicho comportamiento inapropiado para su tarea, y usar la construcción en cuestión es una solución alternativa.

Solo sería extraño usar una sola raise; allí, pero entonces deberíamos haber hablado de utilidad en lugar de significado , como Charlie ha observado cuidadosamente.

Este código no hace nada excepto volver a generar una excepción que ya se generará sin este intento, excepto el bloque. Puede quitarlo con seguridad.

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