Pergunta

Em algum código Delphi 7 Estou mantendo, tenho notado um monte de instâncias do seguinte:

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

Parece-me que esses blocos try pode ser removido, uma vez que eles não fazem nada. No entanto, eu estou desconfiado de possíveis efeitos colaterais sutis ..

Alguém pode pensar em todas as instâncias em que esses blocos poderia realmente fazer qualquer coisa que não aconteceria sem eles lá?

Foi útil?

Solução

Neste contexto, a operação de aumento não tem efeito e deve ser removido becuase seu simplesmente re-levantando a ressalva de que o bloco de exceção apenas pego. aumento é tipicamente utilizado para transferir o controlo para o fim do bloco quando nenhum tratamento de erros apropriada está disponível. No seguinte lidamos com a exceção personalizada, mas qualquer outra exceção deve ser tratado em outro 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;

Tenha cuidado para que não é semelhante à procura forma sem o "raise", que tem o efeito colateral de comer / esconder quaisquer excepções. practicies por desenvolvedores muito sem escrúpulos que espero ter movido para posições com a concorrência.

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

Outras dicas

A remoção do exceto código no trecho de código acima não fará diferença. Você pode (e eu acredito que você deve , uma vez que está reduzindo a legibilidade) removê-lo.

Ok, realmente duas perguntas aqui.

Primeiro, ele é significativa: se ExecSQL lança uma exceção, ele é capturado pelo bloco try e encaminhado para a exceção. Então está encaminhado pelo aumento para o bloco superior.

Em segundo lugar, é útil ? Provavelmente não. É quase certo que é o resultado de uma de três coisas:

  1. Alguém com cabelo pontudo escreveu um padrão de codificação que disse que "todas as operações que podem lançar uma exceção deve ser em um bloco try."
  2. Alguém pretendia voltar e virar as exceções feitas pelo statment execSQL em algum outro, mais significativo, exceção.
  3. Alguém novo não estava ciente de que o que tinha escrito era isomorfo a deixar a preocupação ambiente uter sobre a exceção, e por isso pensei que eles deve encaminhá-lo.

Talvez eu tenha respondido um pouco rápido, ver no final ...
Como é, é inútil para a aplicação .
Período!

Agora, no lado "porquê". Pode ser para padronizar os tratamento de exceções se houver / foi / será / é em outros lugares / algum tipo de código de registro inserido antes do raise:

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

ou por código de limpeza:

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

Atualizar : Não seria um caso em que eu veria algum uso apenas como ele é ...
... para ser capaz de colocar um ponto de interrupção na linha raise, para ter uma chance de ver o que está acontecendo no contexto em que bloco de código.

Este código não faz nada, além de permitir que o programador original para colocar um ponto de interrupção na 'Raise' e ver a exceção mais perto na fonte à sua possível causa. Nesse sentido, uma técnica de depuração perfeitamente razoável.

Na verdade, eu deveria postou isso como comentário às respostas de François, mas eu não sei é que é possível inserir o código formatado há :( Então eu estou postando isso como resposta.

2mghie:

O segundo é completamente unidiomatic, pode-se usar finalmente em seu lugar.

Não, "finalmente" limpeza objeto sempre. "Exceto" - apenas em exceção. Considere o caso de função, que cria, preenchimentos e retornar um 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;

Se você colocar "finalmente" lá - função retornará nil sempre. Se você omitir "tentar" bloco em tudo -. Haverá recursos vazar em caso de exceção em "..."

P.S. Claro, você pode usar "finalmente" e verifique ExceptObj, mas ... não é que feio?

O título contém bastante ampla questão, enquanto a sua explicação dá um exemplo mais específico. Portanto, a minha resposta à questão de como ele procede do exemplo, pode doubtly acrescentar nada útil para o que já foi dito aqui.

Mas, talvez Blorgbeard de fato quer saber se é em tudo significativo para try ... except raise; end. Em Delphi 7, se bem me lembro corretamente, Exit provocaria a parte finally de um bloco try-finally (como se fosse algum tipo de exceção). Alguém pode considerar como um comportamento inadequado para a tarefa, e usando a construção em questão é bastante uma solução alternativa.

Só que ainda seria estranho usar um único raise; lá, mas então devemos ter falado sobre utilidade em vez de meaningfulness , como Charlie foi nitidamente observado.

Este código não faz nada a não ser re-levantar uma exceção que allready ser levantada sem esta tentativa exceto bloco. Você pode removê-lo com segurança.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top