Try...Catch...Finally 문(Visual Basic)
코드를 계속 실행하는 동안 특정 코드 블록에서 발생할 수 있는 일부 또는 모든 오류를 처리하는 방법을 제공합니다.
구문
Try
[ tryStatements ]
[ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
[ catchStatements ]
[ Exit Try ] ]
[ Catch ... ]
[ Finally
[ finallyStatements ] ]
End Try
부분
용어 | 정의 |
---|---|
tryStatements |
선택 사항. 오류가 발생할 수 있는 문입니다. 복합 문일 수 있습니다. |
Catch |
선택 사항. 여러 개의 Catch 블록이 허용됩니다. Try 블록을 처리할 때 예외가 throw되면 각 Catch 문을 텍스트 순서대로 검사하여 예외를 처리하는지 여부를 결정하며, exception 은 throw된 예외를 나타냅니다. |
exception |
선택 사항. 임의의 변수 이름입니다. exception 의 초기 값은 throw된 오류 값입니다. 발견된 오류를 지정하기 위해 Catch 와 함께 사용됩니다. 생략하면 Catch 문이 예외를 catch합니다. |
type |
선택 사항. 클래스 필터의 형식을 지정합니다. exception 의 값이 type 으로 지정된 형식이거나 파생된 형식인 경우 식별자는 예외 개체에 바인딩됩니다. |
When |
선택 사항. When 절이 있는 Catch 문은 expression 이 True 로 평가되는 경우에만 예외를 catch합니다. When 절은 예외의 형식을 확인한 후에만 적용되며, expression 은 예외를 나타내는 식별자를 참조할 수 있다. |
expression |
선택 사항. 암시적으로 Boolean 으로 변환 가능해야 합니다. 제네릭 필터를 설명하는 식입니다. 일반적으로 오류 번호를 기준으로 필터링하는 데 사용됩니다. 오류가 발생하는 상황을 지정하기 위해 When 키워드와 함께 사용됩니다. |
catchStatements |
선택 사항. 연결된 Try 블록에서 발생하는 오류를 처리하는 문입니다. 복합 문일 수 있습니다. |
Exit Try |
선택 사항. Try...Catch...Finally 구조를 벗어나는 키워드입니다. End Try 문 바로 다음의 코드로 실행이 다시 시작됩니다. Finally 문은 계속 실행됩니다. Finally 블록에서는 허용되지 않습니다. |
Finally |
선택 사항. Finally 블록은 실행이 Try...Catch 문의 일부를 벗어날 때 항상 실행됩니다. |
finallyStatements |
선택 사항. 다른 모든 오류 처리가 발생한 후에 실행되는 문입니다. |
End Try |
Try...Catch...Finally 구조를 종료합니다. |
설명
코드의 특정 섹션에서 특정 예외가 발생할 것으로 예상되는 경우 코드를 Try
블록에 넣고 Catch
블록을 사용하여 제어를 보존하고 예외가 발생할 경우 처리합니다.
Try…Catch
문은 Try
블록과 다양한 예외에 대한 처리기를 지정하는 하나 이상의 Catch
절로 구성됩니다. Try
블록에서 예외가 throw되면 Visual Basic은 예외를 처리하는 Catch
문을 찾습니다. 일치하는 Catch
문을 찾을 수 없으면 Visual Basic은 현재 메서드를 호출한 메서드를 검사하는 등 호출 스택을 검사합니다. Catch
블록이 없으면 Visual Basic은 사용자에게 처리되지 않은 예외 메시지를 표시하고 프로그램 실행을 중지합니다.
Try…Catch
문에 두 개 이상의 Catch
문을 사용할 수 있습니다. 이렇게 하면 Catch
절이 순서대로 검사되므로 순서가 중요합니다. Catch 더 구체적인 예외를 덜 구체적인 예외보다 먼저 catch합니다.
다음 Catch
문 조건은 가장 덜 구체적이며 Exception 클래스에서 파생되는 모든 예외를 catch(으)로 처리합니다. 일반적으로 예상되는 특정 예외를 모두 catch한 후 이러한 변형 중 하나를 Try...Catch...Finally
구조의 마지막 Catch
블록으로 사용해야 합니다. 제어 흐름은 이러한 변형 중 하나를 따르는 Catch
블록에 도달할 수 없습니다.
type
은Exception
입니다. 예:Catch ex As Exception
문에
exception
변수가 없습니다. 예:Catch
Try…Catch…Finally
문이 다른 Try
블록에 중첩되면 Visual Basic은 먼저 가장 안쪽 Try
블록의 각 Catch
문을 검사합니다. 일치하는 Catch
문이 없으면 외부 Try…Catch…Finally
블록의 Catch
문으로 검색이 진행됩니다.
Try
블록의 지역 변수는 별도의 블록이기 때문에 Catch
블록에서 사용할 수 없습니다. 둘 이상의 블록에서 변수를 사용하려면 Try...Catch...Finally
구조 외부에서 변수를 선언합니다.
팁
Try…Catch…Finally
문은 IntelliSense 코드 조각으로 사용할 수 있습니다. 코드 조각 관리자에서 코드 패턴 - If, For Each, TryCatch, 속성 등을 확장한 다음 오류 처리(예외)를 확장합니다. 자세한 내용은 코드 조각을 참조하세요.
Finally 블록
Try
구조를 종료하기 전에 실행해야 하는 문이 하나 이상 있는 경우 Finally
블록을 사용합니다. 제어는 Try…Catch
구조를 벗어나기 직전에 Finally
블록으로 전달됩니다. 이는 Try
구조 내부 어디에서나 예외가 발생하는 경우에도 마찬가지입니다.
Finally
블록은 예외가 발생하더라도 실행해야 하는 코드를 실행하는 데 유용합니다. Try...Catch
블록이 종료되는 방식에 관계없이 제어가 Finally
블록으로 전달됩니다.
Finally
블록의 코드는 코드가 Try
또는 Catch
블록에서 Return
문을 발견하더라도 실행됩니다. 다음과 같은 경우 제어가 Try
또는 Catch
블록에서 해당 Finally
블록으로 전달되지 않습니다.
Try
또는Catch
블록에서 End 문이 발견되었습니다.StackOverflowException이
Try
또는Catch
블록에 throw되었습니다.
실행을 Finally
블록으로 명시적으로 전송하는 것은 유효하지 않습니다. 예외를 통하는 경우를 제외하고 Finally
블록 외부로 실행을 전송하는 것은 유효하지 않습니다.
Try
문에 Catch
블록이 하나도 포함되어 있지 않으면 Finally
블록을 포함해야 합니다.
팁
특정 예외를 catch(으)로 지정하지 않으면 Using
문은 Try…Finally
블록처럼 동작하며 블록을 어떻게 종료하는지에 관계없이 리소스의 처리를 보장합니다. 처리되지 않은 예외가 있는 경우에도 마찬가지입니다. 자세한 내용은 using 문을 참조하세요.
Exception 인수
Catch
블록 exception
인수는 Exception 클래스의 인스턴스이거나 Exception
클래스에서 파생된 클래스입니다. Exception
클래스 인스턴스는 Try
블록에서 발생한 오류에 해당합니다.
Exception
개체의 속성은 예외의 원인과 위치를 식별하는 데 도움이 됩니다. 예를 들어, StackTrace 속성은 예외를 발생시킨 호출된 메서드를 나열하여 코드에서 오류가 발생한 위치를 찾는 데 도움을 줍니다. Message는 예외를 설명하는 메시지를 반환합니다. HelpLink는 관련 도움말 파일에 대한 링크를 반환합니다. InnerException은 현재 예외를 발생시킨 Exception
개체를 반환하거나 원본 Exception
이 없는 경우 Nothing
을 반환합니다.
Try…Catch
문 사용 시 고려 사항
비정상적이거나 예상하지 못한 프로그램 이벤트의 발생을 알리는 데에만 Try…Catch
문을 사용합니다. 그 이유는 다음과 같습니다.
런타임에 예외를 catch하면 추가 오버헤드가 발생하고 예외를 피하기 위해 사전 검사하는 것보다 속도가 느려질 수 있습니다.
Catch
블록이 올바르게 처리되지 않으면 예외가 사용자에게 올바르게 보고되지 않을 수 있습니다.예외 처리는 프로그램을 더욱 복잡하게 만듭니다.
발생할 가능성이 있는 조건을 확인하기 위해 항상 Try…Catch
문이 필요한 것은 아닙니다. 다음 예에서는 파일을 열려고 하기 전에 파일이 존재하는지 확인합니다. 이렇게 하면 OpenText 메서드에서 throw된 예외를 catch할 필요성이 줄어듭니다.
Private Sub TextFileExample(ByVal filePath As String)
' Verify that the file exists.
If System.IO.File.Exists(filePath) = False Then
Console.Write("File Not Found: " & filePath)
Else
' Open the text file and display its contents.
Dim sr As System.IO.StreamReader =
System.IO.File.OpenText(filePath)
Console.Write(sr.ReadToEnd)
sr.Close()
End If
End Sub
스레드로부터 안전한 로깅이나 적절한 메시지를 통해 Catch
블록의 코드가 사용자에게 예외를 올바르게 보고할 수 있는지 확인합니다. 그렇지 않으면 예외가 알려지지 않은 채로 남아 있을 수 있습니다.
비동기 메서드
메서드에 async 한정자를 표시하면 메서드에서 await 연산자를 사용할 수 있습니다. Await
연산자가 포함된 문은 대기 중인 작업이 완료될 때까지 메서드 실행을 일시 중지합니다. 작업은 진행 중인 작업을 나타냅니다. Await
연산자와 연결된 작업이 완료되면 동일한 메서드에서 실행이 다시 시작됩니다. 자세한 내용은 비동기 프로그램의 제어 흐름을 참조하세요.
Async 메서드에서 반환된 작업은 처리되지 않은 예외로 인해 완료되었음을 나타내는 오류 상태로 종료될 수 있습니다. 작업이 취소된 상태로 끝날 수도 있으며, 이로 인해 대기 식에서 OperationCanceledException
이 삭제됩니다. 두 가지 예외 유형 중 하나를 catch(으)로 지정하려면 작업과 연결된 Await
표현식을 Try
블록에 배치하고 catch 예외를 Catch
블록에 배치합니다. 이 항목의 뒷부분에 예가 제공됩니다.
여러 예외로 인해 오류가 발생했기 때문에 작업이 오류 상태에 있을 수 있습니다. 예를 들어 작업은 Task.WhenAll 호출의 결과일 수 있습니다. 그러한 작업을 기다릴 때 발견된 예외는 예외 중 하나일 뿐이며 어떤 예외가 발견될지 예측할 수 없습니다. 이 항목의 뒷부분에 예가 제공됩니다.
Await
식은 Catch
블록 또는 Finally
블록 내에 있을 수 없습니다.
반복기
반복기 함수 또는 Get
접근자는 컬렉션에 대해 사용자 지정 반복을 수행합니다. 반복기는 Yield 문을 사용하여 컬렉션의 각 요소를 한 번에 하나씩 반환합니다. For Each...Next 문을 사용하여 반복기 함수를 호출합니다.
Yield
문은 Try
블록 내에 있을 수 있습니다. Yield
문을 포함하는 Try
블록은 Catch
블록과 Finally
블록을 가질 수 있습니다. 예를 보려면 Try 블록을 참조하세요.
Yield
문은 Catch
블록 또는 Finally
블록 내에 있을 수 없습니다.
반복기 함수 외부의 For Each
본문에서 예외가 throw되면 반복기 함수의 Catch
블록이 실행되지 않지만 반복기 함수의 Finally
블록이 실행됩니다. 반복기 함수 내의 Catch
블록은 반복기 함수 내에서 발생하는 예외만 catch합니다.
부분 신뢰 상황
네트워크 공유에서 호스팅되는 애플리케이션과 같은 부분 신뢰 상황에서 Try...Catch...Finally
은(는) 호출이 포함된 메서드가 호출되기 전에 발생하는 보안 예외를 catch(으)로 처리하지 않습니다. 다음 예를 서버 공유에 배치하고 여기에서 실행하면 "System.Security.SecurityException: 요청 실패" 오류가 발생합니다. 보안 예외에 대한 자세한 내용은 SecurityException 클래스를 참조하세요.
Try
Process.Start("http://www.microsoft.com")
Catch ex As Exception
Console.WriteLine("Can't load Web page" & vbCrLf & ex.Message)
End Try
이러한 부분 신뢰 상황에서는 Process.Start
문을 별도의 Sub
에 넣어야 합니다. Sub
에 대한 초기 호출이 실패합니다. 이렇게 하면 Process.Start
이(가) 포함된 Sub
이(가) 시작되고 보안 예외가 생성되기 전에 Try...Catch
에서 catch이(가) 활성화됩니다.
예제
Try...Catch...Finally
의 구조
다음 예에서는 Try...Catch...Finally
문의 구조를 보여 줍니다.
Public Sub TryExample()
' Declare variables.
Dim x As Integer = 5
Dim y As Integer = 0
' Set up structured error handling.
Try
' Cause a "Divide by Zero" exception.
x = x \ y
' This statement does not execute because program
' control passes to the Catch block when the
' exception occurs.
Console.WriteLine("end of Try block")
Catch ex As Exception
' Show the exception's message.
Console.WriteLine(ex.Message)
' Show the stack trace, which is a list of methods
' that are currently executing.
Console.WriteLine("Stack Trace: " & vbCrLf & ex.StackTrace)
Finally
' This line executes whether or not the exception occurs.
Console.WriteLine("in Finally block")
End Try
End Sub
Try
블록에서 호출된 메서드의 예외
다음 예에서 CreateException
메서드는 NullReferenceException
을 throw합니다. 예외를 생성하는 코드가 Try
블록에 없습니다. 따라서 CreateException
메서드는 예외를 처리하지 않습니다. CreateException
메서드에 대한 호출이 Try
블록에 있으므로 RunSample
메서드는 예외를 처리합니다.
이 예에는 가장 구체적인 것부터 가장 일반적인 것 순으로 순서가 지정된 여러 형식의 예외에 대한 Catch
문이 포함되어 있습니다.
Public Sub RunSample()
Try
CreateException()
Catch ex As System.IO.IOException
' Code that reacts to IOException.
Catch ex As NullReferenceException
Console.WriteLine("NullReferenceException: " & ex.Message)
Console.WriteLine("Stack Trace: " & vbCrLf & ex.StackTrace)
Catch ex As Exception
' Code that reacts to any other exception.
End Try
End Sub
Private Sub CreateException()
' This code throws a NullReferenceException.
Dim obj = Nothing
Dim prop = obj.Name
' This code also throws a NullReferenceException.
'Throw New NullReferenceException("Something happened.")
End Sub
Catch When 문
다음 예에서는 Catch When
문을 사용하여 조건식을 필터링하는 방법을 보여 줍니다. 조건식이 True
로 평가되면 Catch
블록의 코드가 실행됩니다.
Private Sub WhenExample()
Dim i As Integer = 5
Try
Throw New ArgumentException()
Catch e As OverflowException When i = 5
Console.WriteLine("First handler")
Catch e As ArgumentException When i = 4
Console.WriteLine("Second handler")
Catch When i = 5
Console.WriteLine("Third handler")
End Try
End Sub
' Output: Third handler
중첩 Try
문
다음 예에는 Try
블록에 포함된 Try…Catch
문이 있습니다. 내부 Catch
블록은 InnerException
속성 집합이 원래 예외로 설정된 예외를 throw합니다. 외부 Catch
블록은 자체 예외와 내부 예외를 보고합니다.
Private Sub InnerExceptionExample()
Try
Try
' Set a reference to a StringBuilder.
' The exception below does not occur if the commented
' out statement is used instead.
Dim sb As System.Text.StringBuilder
'Dim sb As New System.Text.StringBuilder
' Cause a NullReferenceException.
sb.Append("text")
Catch ex As Exception
' Throw a new exception that has the inner exception
' set to the original exception.
Throw New ApplicationException("Something happened :(", ex)
End Try
Catch ex2 As Exception
' Show the exception.
Console.WriteLine("Exception: " & ex2.Message)
Console.WriteLine(ex2.StackTrace)
' Show the inner exception, if one is present.
If ex2.InnerException IsNot Nothing Then
Console.WriteLine("Inner Exception: " & ex2.InnerException.Message)
Console.WriteLine(ex2.StackTrace)
End If
End Try
End Sub
비동기 메서드에 대한 예외 처리
다음 예제에서는 비동기 메서드에 대한 예외 처리를 보여 줍니다. 비동기 작업에 적용되는 catch 예외에 대해 Await
표현식은 호출자의 Try
블록에 있고 예외는 Catch
블록에서 catch됩니다.
예제에서 Throw New Exception
줄의 주석 처리를 제거하여 예외 처리를 보여 줍니다. 예외가 Catch
블록에서 catch되고 작업의 IsFaulted
속성이 True
로 설정되고, 작업의 Exception.InnerException
속성이 예외로 설정됩니다.
Throw New OperationCancelledException
줄의 주석 처리를 제거하여 비동기 프로세스를 취소할 수 있을 때 발생하는 동작을 보여 줍니다. 예외가 Catch
블록에서 catch되고 작업의 IsCanceled
속성이 True
로 설정됩니다. 그러나 이 예에 적용되지 않는 일부 조건에서는 IsFaulted
가 True
로 설정되고 IsCanceled
가 False
로 설정됩니다.
Public Async Function DoSomethingAsync() As Task
Dim theTask As Task(Of String) = DelayAsync()
Try
Dim result As String = Await theTask
Debug.WriteLine("Result: " & result)
Catch ex As Exception
Debug.WriteLine("Exception Message: " & ex.Message)
End Try
Debug.WriteLine("Task IsCanceled: " & theTask.IsCanceled)
Debug.WriteLine("Task IsFaulted: " & theTask.IsFaulted)
If theTask.Exception IsNot Nothing Then
Debug.WriteLine("Task Exception Message: " &
theTask.Exception.Message)
Debug.WriteLine("Task Inner Exception Message: " &
theTask.Exception.InnerException.Message)
End If
End Function
Private Async Function DelayAsync() As Task(Of String)
Await Task.Delay(100)
' Uncomment each of the following lines to
' demonstrate exception handling.
'Throw New OperationCanceledException("canceled")
'Throw New Exception("Something happened.")
Return "Done"
End Function
' Output when no exception is thrown in the awaited method:
' Result: Done
' Task IsCanceled: False
' Task IsFaulted: False
' Output when an Exception is thrown in the awaited method:
' Exception Message: Something happened.
' Task IsCanceled: False
' Task IsFaulted: True
' Task Exception Message: One or more errors occurred.
' Task Inner Exception Message: Something happened.
' Output when an OperationCanceledException or TaskCanceledException
' is thrown in the awaited method:
' Exception Message: canceled
' Task IsCanceled: True
' Task IsFaulted: False
비동기 메서드에서 여러 예외 처리
다음 예제에서는 여러 작업에서 여러 예외가 발생할 수 있는 경우 예외 처리를 보여 줍니다. Try
블록에는 Task.WhenAll이 반환한 작업에 대한 Await
식이 있습니다. Task.WhenAll이 적용된 세 가지 작업이 완료되면 작업이 완료됩니다.
세 작업에서 각각 예외가 발생합니다. Catch
블록은 Task.WhenAll
이 반환한 작업의 Exception.InnerExceptions
속성에 있는 예외를 반복합니다.
Public Async Function DoMultipleAsync() As Task
Dim theTask1 As Task = ExcAsync(info:="First Task")
Dim theTask2 As Task = ExcAsync(info:="Second Task")
Dim theTask3 As Task = ExcAsync(info:="Third Task")
Dim allTasks As Task = Task.WhenAll(theTask1, theTask2, theTask3)
Try
Await allTasks
Catch ex As Exception
Debug.WriteLine("Exception: " & ex.Message)
Debug.WriteLine("Task IsFaulted: " & allTasks.IsFaulted)
For Each inEx In allTasks.Exception.InnerExceptions
Debug.WriteLine("Task Inner Exception: " + inEx.Message)
Next
End Try
End Function
Private Async Function ExcAsync(info As String) As Task
Await Task.Delay(100)
Throw New Exception("Error-" & info)
End Function
' Output:
' Exception: Error-First Task
' Task IsFaulted: True
' Task Inner Exception: Error-First Task
' Task Inner Exception: Error-Second Task
' Task Inner Exception: Error-Third Task
참고 항목
.NET