finally 블록에서 예외가 발생하면 정확히 어떻게됩니까?
특히, 예외가 finally 블록의 중간에 발생하면 어떻게됩니까? 이 블록의 나머지 부분 (이후)이 호출됩니까?
예외가 위쪽으로 전파된다는 것을 알고 있습니다.
답변
finally 블록에서 예외 가 발생 하면 정확히 어떻게됩니까?
그 예외는 계속해서 전파되고 더 높은 수준에서 처리 될 수 있습니다.
최종 차단은 예외가 발생한 지점을 넘어 완료 되지 않습니다 .
이전 예외를 처리하는 동안 finally 블록이 실행 된 경우 첫 번째 예외가 손실됩니다.
C # 4 언어 사양 § 8.9.5 : finally 블록에서 다른 예외가 발생하면 현재 예외 처리가 종료됩니다.
답변
이와 같은 질문에 대해서는 일반적으로 Visual Studio에서 빈 콘솔 응용 프로그램 프로젝트를 열고 작은 샘플 프로그램을 작성하십시오.
using System;
class Program
{
static void Main(string[] args)
{
try
{
try
{
throw new Exception("exception thrown from try block");
}
catch (Exception ex)
{
Console.WriteLine("Inner catch block handling {0}.", ex.Message);
throw;
}
finally
{
Console.WriteLine("Inner finally block");
throw new Exception("exception thrown from finally block");
Console.WriteLine("This line is never reached");
}
}
catch (Exception ex)
{
Console.WriteLine("Outer catch block handling {0}.", ex.Message);
}
finally
{
Console.WriteLine("Outer finally block");
}
}
}
프로그램을 실행하면 당신이하는 정확한 순서가 표시됩니다 catch
및 finally
실행 블록을. 예외가 발생한 후 finally 블록의 코드는 실행되지 않습니다 (실제로이 샘플 프로그램에서는 Visual Studio에서 도달 할 수없는 코드가 감지되었음을 경고합니다).
try 블록에서 발생한 내부 catch 블록 처리 예외입니다. 이너 드디어 차단 finally 블록에서 발생한 외부 catch 블록 처리 예외 외부는 마지막으로 차단
추가 비고
Michael Damatov가 지적했듯이 try
(내부) catch
블록 에서 처리하지 않으면 블록 의 예외 가 “먹게”됩니다 . 실제로 위의 예에서 재발 사 예외는 외부 캐치 블록에 나타나지 않습니다. 다음과 같이 약간 수정 된 샘플을보다 명확하게 확인하십시오.
using System;
class Program
{
static void Main(string[] args)
{
try
{
try
{
throw new Exception("exception thrown from try block");
}
finally
{
Console.WriteLine("Inner finally block");
throw new Exception("exception thrown from finally block");
Console.WriteLine("This line is never reached");
}
}
catch (Exception ex)
{
Console.WriteLine("Outer catch block handling {0}.", ex.Message);
}
finally
{
Console.WriteLine("Outer finally block");
}
}
}
출력에서 볼 수 있듯이 내부 예외는 “손실”입니다 (예 : 무시).
이너 드디어 차단 finally 블록에서 발생한 외부 catch 블록 처리 예외 외부는 마지막으로 차단
답변
보류중인 예외가있는 경우 ( try
블록이 finally
있지만 아니오 인 경우 catch
) 새 예외가 해당 예외를 대체합니다.
보류중인 예외가 없으면 finally
블록 외부에서 예외를 throw하는 것처럼 작동합니다 .
답변
예외가 전파됩니다.
답변
원래 예외 가 더 중요한 경우 “원래 예외”( try
블록 에서 발생)를 저장 하고 “최종 예외”(블록 에서 발생)를 저장하는 빠른 (그리고 명백한) 스 니펫 finally
:
try
{
throw new Exception("Original Exception");
}
finally
{
try
{
throw new Exception("Finally Exception");
}
catch
{ }
}
위의 코드가 실행되면 “Original Exception”이 호출 스택을 전파하고 “Finally Exception”이 손실됩니다.
답변
예외로 인해 결코 열리지 않은 스트림을 닫으려고하는 동안 오류를 잡기 위해이 작업을 수행해야했습니다.
errorMessage = string.Empty;
try
{
byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(xmlFileContent);
webRequest = WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.ContentType = "text/xml;charset=utf-8";
webRequest.ContentLength = requestBytes.Length;
//send the request
using (var sw = webRequest.GetRequestStream())
{
sw.Write(requestBytes, 0, requestBytes.Length);
}
//get the response
webResponse = webRequest.GetResponse();
using (var sr = new StreamReader(webResponse.GetResponseStream()))
{
returnVal = sr.ReadToEnd();
sr.Close();
}
}
catch (Exception ex)
{
errorMessage = ex.ToString();
}
finally
{
try
{
if (webRequest.GetRequestStream() != null)
webRequest.GetRequestStream().Close();
if (webResponse.GetResponseStream() != null)
webResponse.GetResponseStream().Close();
}
catch (Exception exw)
{
errorMessage = exw.ToString();
}
}
webRequest가 생성되었지만 연결 오류가 발생한 경우
using (var sw = webRequest.GetRequestStream())
마지막으로 webRequest가 생성되어 열려 있다고 생각되는 연결을 닫으려고 시도하는 예외가 발생합니다.
마지막으로 try-catch가 내부에 없으면이 코드는 webRequest를 정리하는 동안 처리되지 않은 예외를 발생시킵니다.
if (webRequest.GetRequestStream() != null)
거기에서 코드는 발생한 오류를 올바르게 처리하지 않고 종료되므로 호출 메소드에 문제가 발생합니다.
이것이 도움이되기를 바랍니다.
답변
다른 예외가 활성화 된 상태에서 예외를 발생 시키면 첫 번째 예외가 두 번째 (나중) 예외로 대체됩니다.
다음은 어떤 일이 일어나는지 보여주는 코드입니다.
public static void Main(string[] args)
{
try
{
try
{
throw new Exception("first exception");
}
finally
{
//try
{
throw new Exception("second exception");
}
//catch (Exception)
{
//throw;
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
- 코드를 실행하면 “두 번째 예외”가 표시됩니다
- try 및 catch 문을 주석 해제하면 “첫 번째 예외”가 표시됩니다
- 또한 던지기의 주석 처리를 제거하십시오. “두 번째 예외”가 다시 나타납니다.