[c#] Try / finally (Catch 제외)에서 예외가 발생합니까?
나는 대답이 ‘예’라고 거의 긍정적입니다. Try finally 블록을 사용하지만 Catch 블록을 사용하지 않으면 예외가 발생합니다. 옳은?
일반적으로 연습에 대한 의견이 있습니까?
세스
답변
네, 당연합니다. finally
물론, 당신의 블록이 예외를 던지지 않는다고 가정하면 , 이것은 원래 던진 것을 효과적으로 “대체”할 것입니다.
답변
일반적으로 연습에 대한 의견이 있습니까?
예. 조심해 . finally 블록이 실행 중일 때 처리되지 않은 예기치 않은 예외가 발생 했기 때문에 실행 중일 가능성이 있습니다 . 즉 , 무언가가 고장 났고 완전히 예상치 못한 일이 발생할 수 있습니다.
이 상황에서 finally 블록에서 코드를 전혀 실행하지 말아야 할 경우입니다. finally 블록의 코드는 종속 된 하위 시스템이 실제로는 심각하게 손상 될 수 있지만 정상이라고 가정하도록 빌드 될 수 있습니다. finally 블록의 코드는 상황을 악화시킬 수 있습니다.
예를 들어, 나는 종종 이런 종류의 것을 봅니다.
DisableAccessToTheResource();
try
{
DoSomethingToTheResource();
}
finally
{
EnableAccessToTheResource();
}
이 코드의 작성자는 “나는 세계의 상태를 일시적으로 변경하고 있습니다. 상태를 호출되기 전의 상태로 복원해야합니다”라고 생각합니다. 그러나 이것이 잘못 될 수있는 모든 방법에 대해 생각해 봅시다.
첫째, 호출자가 리소스에 대한 액세스를 이미 비활성화했을 수 있습니다. 이 경우이 코드는 아마 조기에 다시 활성화합니다.
둘째, DoSomethingToTheResource에서 예외가 발생하면 리소스에 대한 액세스를 활성화하는 것이 옳은 일입니까 ??? 리소스를 관리하는 코드가 예기치 않게 손상되었습니다 . 이 코드는 사실상 “관리 코드가 손상된 경우 다른 코드가 가능한 한 빨리 해당 코드를 호출 할 수 있는지 확인하여 끔찍하게 실패 할 수 있도록합니다 .”라고 말합니다. 이것은 나쁜 생각 인 것 같습니다.
셋째, DoSomethingToTheResource에서 예외가 발생하면 EnableAccessToTheResource도 예외를 발생시키지 않는다는 것을 어떻게 알 수 있습니까? 리소스 사용으로 인한 끔찍한 일이 무엇이든간에 정리 코드에 영향을 미칠 수 있으며,이 경우 원래 예외가 손실되고 문제를 진단하기가 더 어려워집니다.
try-finally 블록을 사용하지 않고 다음과 같은 코드를 작성하는 경향이 있습니다.
bool wasDisabled = IsAccessDisabled();
if (!wasDisabled)
DisableAccessToTheResource();
DoSomethingToTheResource();
if (!wasDisabled)
EnableAccessToTheResource();
이제 상태는 필요하지 않는 한 변경되지 않습니다. 이제 발신자의 상태가 엉망이되지 않습니다. 이제 DoSomethingToTheResource가 실패하면 액세스를 다시 활성화하지 않습니다. 우리는 무언가가 심하게 손상되었다고 가정하고 코드를 계속 실행하여 상황을 악화시킬 위험이 없습니다. 가능한 경우 호출자가 문제를 처리하도록하십시오.
그렇다면 finally 블록을 실행하는 것이 좋은 생각은 언제입니까? 첫째, 예외가 예상되는 경우. 예를 들어, 다른 사람이 파일을 잠 갔기 때문에 파일을 잠 그려는 시도가 실패 할 것으로 예상 할 수 있습니다. 이 경우 예외를 포착하여 사용자에게보고하는 것이 좋습니다. 이 경우 무엇이 깨 졌는지에 대한 불확실성이 줄어 듭니다. 청소로 상황을 악화시킬 가능성은 거의 없습니다.
둘째, 정리하는 리소스가 부족한 시스템 리소스 일 때. 예를 들어 finally 블록에서 파일 핸들을 닫는 것이 좋습니다. ( “사용”은 물론 try-finally 블록을 작성하는 또 다른 방법입니다.) 파일의 내용이 손상되었을 수 있지만 지금은 할 수있는 일이 없습니다. 파일 핸들은 결국 닫힐 것이므로 나중에보다는 더 빠를 수도 있습니다.