예외 처리: try...with 식
예외 처리: try...with 식
F#에서 예외를 처리하는 데 쓰는 try...with 식을 설명하는 주제예요. 코드가 실행되는 도중 오류가 나도 프로그램이 멈추지 않고, 그 오류를 잡아 적절히 대응하도록 해 주는 장치죠.
본문
구문
try
expression1
with
| pattern1 -> expression2
| pattern2 -> expression3
...
설명
try...with 식은 F#에서 예외를 처리하는 데 사용해요. C#의 try...catch 문과 비슷한 개념이죠. 위 구문에서 expression1의 코드가 예외를 발생시킬 수 있어요. try...with 식은 값을 반환한다는 점이 핵심이에요.
예외가 발생하지 않으면 전체 식은 expression1의 값을 반환해요. 예외가 발생하면 각 패턴이 예외와 차례로 비교되고, 첫 번째로 일치하는 패턴에 해당하는 식(이걸 예외 처리기라고 해요)이 실행되어 전체 식은 그 예외 처리기에 있는 식의 값을 반환해요. 만약 어떤 패턴도 일치하지 않으면, 예외는 일치하는 처리기를 찾을 때까지 호출 스택을 타고 위로 전파되어요.
예외 처리기에 있는 각 식이 반환하는 값의 타입은 try 블록 안의 식이 반환하는 타입과 반드시 일치해야 해요.
오류가 발생했다는 사실은 종종 예외 처리기의 각 식에서 돌려줄 유효한 값이 없다는 뜻이기도 해요. 그래서 자주 쓰는 패턴은 식의 타입을 옵션 타입(option type)으로 두는 거예요. 다음 코드가 그 패턴을 보여 줘요.
let divide1 x y =
try
Some (x / y)
with
| :? System.DivideByZeroException -> printfn "Division by zero!"; None
let result1 = divide1 100 0
예외는 .NET 예외일 수도 있고, F# 예외일 수도 있어요. F# 예외는 exception 키워드로 직접 정의할 수 있어요.
예외 타입이나 기타 조건으로 필터링할 때 다양한 패턴을 쓸 수 있는데, 그 옵션을 다음 표로 정리했어요.
| 패턴 | 설명 |
|---|---|
:? exception-type |
지정한 .NET 예외 타입과 일치시켜요. |
:? exception-type as identifier |
지정한 .NET 예외 타입과 일치시키되, 예외에 이름을 붙인 값으로 만들어 줘요. |
exception-name(arguments) |
F# 예외 타입과 일치시키고 인자를 바인딩해요. |
identifier |
어떤 예외든 일치시키고 이름을 예외 객체에 바인딩해요. :? System.Exception as identifier와 동등해요. |
identifier when condition |
조건이 참이면 어떤 예외든 일치시켜요. |
예제
다음 코드 예제들이 각각의 예외 처리기 패턴을 어떻게 쓰는지 보여 줘요.
// 이 예제는 .NET 예외에 이름을 붙이기 위해 as 키워드를 사용하는 모습을 보여 줘요.
let divide2 x y =
try
Some( x / y )
with
| :? System.DivideByZeroException as ex -> printfn "Exception! %s " (ex.Message); None
// 이 버전은 조건을 사용해 같은 예외를 여러 경로로 분기하는 모습을 보여 줘요.
let divide3 x y flag =
try
x / y
with
| ex when flag -> printfn "TRUE: %s" (ex.ToString()); 0
| ex when not flag -> printfn "FALSE: %s" (ex.ToString()); 1
let result2 = divide3 100 0 true
// 이 버전은 F# 예외를 사용하는 모습을 보여 줘요.
exception Error1 of string
exception Error2 of string * int
let function1 x y =
try
if x = y then raise (Error1("x"))
else raise (Error2("x", 10))
with
| Error1(str) -> printfn "Error1 %s" str
| Error2(str, i) -> printfn "Error2 %s %d" str i
function1 10 10
function1 9 2
참고
try...with구조는try...finally식과 별개의 식이에요. 그래서 코드에with블록과finally블록이 둘 다 필요하다면, 두 식을 중첩해서 써야 해요.
참고
try...with는 async 식, task 식, 그리고 기타 계산 식(computation expression) 안에서도 쓸 수 있어요. 이 경우try...with식의 맞춤형 버전이 사용돼요. 자세한 내용은 Async Expressions, Task Expressions, Computation Expressions를 참고하세요.
더 알아보기 (Learn more)
- 예외 처리 (Exception Handling)
- 예외 타입 (Exception Types)
- 예외 처리:
try...finally식 (Exceptions: Thetry...finallyExpression)