C#에서 런타임에 프로그램의 오류는 예외라는 메커니즘을 사용하여 프로그램을 통해 전파됩니다. 오류가 발생하는 코드에서 예외를 throw하고, 오류를 수정할 수 있는 코드에서 예외를 catch합니다. .NET 런타임이나 프로그램의 코드에서 예외를 throw할 수 있습니다. ** 예외가 발생하면 예외에 대한 문이 발견될 때까지 호출 스택을 통해 전파됩니다. 처리되지 않은 예외는 시스템이 제공하는 일반적인 예외 처리기에 의해 처리되어 대화 상자가 표시됩니다.
예외는 에서 파생된 Exception클래스로 표시됩니다. 이 클래스는 예외 유형을 식별하고 예외에 대한 세부 정보가 있는 속성을 포함합니다. 예외를 throw하려면 예외 파생 클래스의 인스턴스를 만들고, 필요에 따라 예외의 속성을 구성한 다음, 키워드를 사용하여 throw
개체를 throw해야 합니다. 다음은 그 예입니다.
class CustomException : Exception
{
public CustomException(string message)
{
}
}
private static void TestThrow()
{
throw new CustomException("Custom exception in TestThrow()");
}
예외가 throw된 후 런타임은 현재 문을 검사하여 블록 내에 try
있는지 확인합니다. 만약 그렇다면, catch
블록과 연결된 모든 try
블록을 검사하여 예외를 처리할 수 있는지 확인합니다.
Catch
블록은 일반적으로 예외 형식을 지정합니다. 블록의 catch
형식이 예외와 동일한 형식이거나 예외의 기본 클래스이면 블록에서 catch
메서드를 처리할 수 있습니다. 다음은 그 예입니다.
try
{
TestThrow();
}
catch (CustomException ex)
{
System.Console.WriteLine(ex.ToString());
}
예외를 throw하는 문이 try
블록 내에 없거나 해당 try
블록에 일치하는 catch
블록이 없는 경우, 런타임은 호출된 메서드에 try
문과 catch
블록이 있는지 확인합니다. 런타임은 호출 스택을 계속하여 호환되는 catch
블록을 검색합니다.
catch
블록을 찾아서 실행한 후에는 해당 블록 뒤의 다음 문으로 컨트롤이 catch
전달됩니다.
문에는 try
둘 catch
이상의 블록이 포함될 수 있습니다. 예외를 처리할 수 있는 첫 번째 catch
문이 실행됩니다. 호환되는 경우에도 다음 catch
문은 무시됩니다. 가장 구체적인(또는 가장 파생된)에서 최소 특정 항목으로 catch 블록을 정렬합니다. 다음은 그 예입니다.
using System;
using System.IO;
namespace Exceptions
{
public class CatchOrder
{
public static void Main()
{
try
{
using (var sw = new StreamWriter("./test.txt"))
{
sw.WriteLine("Hello");
}
}
// Put the more specific exceptions first.
catch (DirectoryNotFoundException ex)
{
Console.WriteLine(ex);
}
catch (FileNotFoundException ex)
{
Console.WriteLine(ex);
}
// Put the least specific exception last.
catch (IOException ex)
{
Console.WriteLine(ex);
}
Console.WriteLine("Done");
}
}
}
블록이 catch
실행되기 전에 런타임은 finally
블록을 확인합니다.
Finally
차단을 사용하면 프로그래머가 중단된 try
블록에서 남은 모호한 상태를 정리하거나 런타임에서 가비지 수집기가 개체를 완료할 때까지 기다리지 않고 외부 리소스(예: 그래픽 핸들, 데이터베이스 연결 또는 파일 스트림)를 해제할 수 있습니다. 다음은 그 예입니다.
static void TestFinally()
{
FileStream? file = null;
//Change the path to something that works on your machine.
FileInfo fileInfo = new System.IO.FileInfo("./file.txt");
try
{
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
}
finally
{
// Closing the file allows you to reopen it immediately - otherwise IOException is thrown.
file?.Close();
}
try
{
file = fileInfo.OpenWrite();
Console.WriteLine("OpenWrite() succeeded");
}
catch (IOException)
{
Console.WriteLine("OpenWrite() failed");
}
}
WriteByte()
이(가) 예외를 발생시킨 경우 try
이(가) 호출되지 않으면 파일을 다시 여는 두 번째 file.Close()
블록의 코드가 실패하게 되어 파일이 잠긴 상태로 유지됩니다. 예외가 발생하더라도 finally
블록이 실행되기 때문에, 이전 예제의 finally
블록은 파일을 정확하게 닫아 오류를 피하는 데 도움이 됩니다.
예외가 throw된 후 호출 스택에서 호환 가능한 catch
블록을 찾을 수 없는 경우 다음 세 가지 중 하나가 발생합니다.
- 예외가 종료자 내에 있으면 종료자가 중단되고 기본 종료자(있는 경우)가 호출됩니다.
- 호출 스택에 정적 생성자 또는 정적 필드 이니셜라이저 TypeInitializationException 가 포함되어 있으면 원래 예외가 새 예외의 속성에 InnerException 할당된 상태에서 throw됩니다.
- 스레드의 시작에 도달하면 스레드가 종료됩니다.
.NET