[C#] {…} 시도가 마지막으로 {…} 좋은 이유는 무엇입니까? {…} 잡기 {}를 해보십시오.

나는 사람들이 인수없이 catch를 사용하는 것이 좋지 않은 형태라고 말한 것을 보았습니다. 특히 catch가 아무것도하지 않으면 :

StreamReader reader=new  StreamReader("myfile.txt");
try
{
  int i = 5 / 0;
}
catch   // No args, so it will catch any exception
{}
reader.Close();

그러나 이것은 좋은 형태로 간주됩니다.

StreamReader reader=new  StreamReader("myfile.txt");
try
{
  int i = 5 / 0;
}
finally   // Will execute despite any exception
{
  reader.Close();
}

내가 알 수있는 한, finally 블록에 정리 코드를 넣는 것과 try..catch 블록 뒤에 정리 코드를 넣는 것의 유일한 차이점은 try 블록에 return 문이있는 경우입니다 (이 경우 정리 코드는 실행하지만 try..catch 이후의 코드는 실행되지 않습니다).

그렇지 않으면, 마지막으로 특별한 점은 무엇입니까?



답변

가장 큰 차이점은 try...catch오류가 발생했다는 사실을 숨기고 예외를 삼킨다 는 것 입니다. try..finally정리 코드를 실행 한 다음 예외가 계속 진행되어 처리 방법을 알고있는 것으로 처리됩니다.


답변

“마침내”는 “프로그램 상태가 정상인지 확인하기 위해 항상 수행해야하는 것”의 진술입니다. 따라서 예외로 인해 프로그램 상태가 중단 될 가능성이있는 경우 항상 하나를 갖는 것이 좋습니다. 컴파일러는 또한 최종 코드가 실행되도록하기 위해 많은 노력을 기울입니다.

“캐치”는 “이 예외에서 복구 할 수 있습니다”라는 문구입니다. 당신은 당신이 정말로 고칠 수있는 예외들로부터 만 회복해야합니다. 논란없이 catch는 “이봐, 나는 무엇이든 복구 할 수 있습니다!”라고 말합니다. 이것은 거의 항상 사실이 아닙니다.

모든 예외에서 회복 할 수 있다면 , 의도를 선언 한 것에 대한 의미 론적 문제 일 것입니다. 그러나 그렇지 않으며 거의 ​​확실하게 특정 프레임을 처리하여 특정 예외를 처리하는 것이 좋습니다. 따라서 마지막으로 사용하여 정리 코드를 무료로 실행하지만 지식이 풍부한 처리기가 문제를 처리하도록하십시오.


답변

한 줄에서 예외가 발생하면 알 수 없기 때문입니다.

첫 번째 코드 블록을 사용하면 예외가 단순히 흡수 되고 프로그램 상태가 잘못되었을 때에도 프로그램은 계속 실행됩니다.

두 번째 블록으로, 예외가 될 것입니다 던져 최대 거품 하지만reader.Close()여전히 실행이 보장됩니다.

예외가 예상되지 않으면 try..catch 블록을 넣지 마십시오. 프로그램이 잘못된 상태가되었을 때 나중에 디버깅하기가 어려우며 그 이유를 알 수 없습니다.


답변

결국 무엇이든 실행됩니다. 따라서 try 블록이 성공하면 try 블록이 실행되고 try 블록이 실패하면 catch 블록을 실행 한 다음 finally 블록을 실행합니다.

또한 다음 구문을 사용하는 것이 좋습니다.

using (StreamReader reader=new  StreamReader("myfile.txt"))
{
}

using 문이 try / finally에 자동으로 래핑되므로 스트림이 자동으로 닫힙니다. (실제로 예외를 잡으려면 using 문 주위에 try / catch를 넣어야합니다).


답변

다음 2 개의 코드 블록은 동일하지만 동일하지 않습니다.

try
{
  int i = 1/0;
}
catch
{
  reader.Close();
  throw;
}

try
{
  int i = 1/0;
}
finally
{
  reader.Close();
}
  1. ‘마지막’은 의도를 밝히는 코드입니다. 컴파일러와 다른 프로그래머에게이 코드가 무엇이든 실행되어야한다고 선언합니다.
  2. 캐치 블록이 여러 개이고 정리 코드가 있으면 마지막으로 필요합니다. 마지막으로, 각 catch 블록에서 정리 코드를 복제합니다. (건조 원리)

마지막으로 블록은 특별하다. CLR은 catch 블록과 별도로 finally 블록을 사용하여 코드를 인식하고 처리하며 CLR은 finally 블록이 항상 실행되도록 보장합니다. 컴파일러의 구문 설탕이 아닙니다.


답변

나는 여기에 합의 인 것처럼 보인다-빈 ‘catch’는 try 블록에서 발생했을 수있는 예외를 가리기 때문에 나쁘다.

또한 가독성 관점에서 ‘try’블록을 볼 때 해당 ‘catch’문이 있다고 가정합니다. ‘finally’블록에서 자원이 할당 해제되도록하기 위해 ‘try’만 사용하는 경우 대신 ‘using’문을 고려할 수 있습니다 .

using (StreamReader reader = new StreamReader('myfile.txt'))
{
    // do stuff here
} // reader.dispose() is called automatically

IDisposable을 구현하는 모든 개체에 ‘using’문을 사용할 수 있습니다. 객체의 dispose () 메서드는 블록 끝에서 자동으로 호출됩니다.


답변

Try..Catch..Finally메소드가 예외를 로컬로 처리하는 방법을 알고있는 경우을 사용하십시오 . 예외는 Try, Handled in Catch에서 발생하며 정리 후에는 Final에서 수행됩니다.

메소드가 예외를 처리하는 방법을 모르지만 일단 발생하면 정리가 필요한 경우 사용 Try..Finally

이로 인해 예외는 호출 메소드로 전파되고 호출 메소드에 적합한 Catch 문이있는 경우 처리됩니다. 현재 메소드 또는 호출 메소드에 예외 핸들러가 없으면 애플리케이션이 충돌합니다.

으로 Try..Finally로컬 정리가 호출 방법에 예외를 전파하기 전에 수행되는 것을 보장한다.