티스토리 뷰

프로그래밍

VB.Net 함수와 프로시저

야라바 2015. 4. 1. 15:19


프로그램이 길어지고 복잡해 질수록 연관성 있는 코드를 별도의 묶음으로 분리해 놓으면 프로그램의 가독성이 높아지는 것은 물론이고 해당 코드가 필요한 곳에서는 언제든지 호출하여 사용할 수 있으므로 재사용성을 높이고 오류의 가능성을 최소화하는 효과를 가져올 수 있습니다. 이렇게 특정 기능을 수행하는 단위로 분할하여 묶어 놓는 작업을 모듈화라고 하며 아래의 VB.Net 콘솔 프로젝트의 기본 코드에서도 확인할 수 있지만 모든 프로그램은 하나 이상의 프로시저로 구성된다 할 수 있습니다. 

Module Module1
    Sub Main()

    End Sub
End Module

VB.Net은 서브 프로시저와 함수(function) 두가지 형태의 프로시저(Procedure)를 정의해서 사용할 수 있습니다. 서브 프로시저와 함수는 프로시저 종료 시점에 호출한 곳에서 값을 돌려받을 수 있으면 함수, 받을 수 없으면 서브 프로시저라는 차이점 외에는 동일합니다.

    Public Sub ToggleStatusIcon(ByVal Status As Boolean)
        StatusIcon.Visible = Status And (Not CommandLine.Silent)
        StatusIconVisible = StatusIcon.Visible
    End Sub

    Public Function Translate(ByVal Code As String, _
                                        Optional ByVal DefaultValue As String = "") As String
        If Code = Nothing OrElse Code = "" Then Return DefaultValue
        Return If(Strings.ContainsKey(Code), Strings(Code), 
                    If(DefaultValue = "", Code, DefaultValue))
    End Function

    //......
    Interaction.StatusIcon.ContextMenuStrip = Nothing
    AddHandler Interaction.StatusIcon.Click, AddressOf StatusIcon_Click
    
    Interaction.StatusIcon.Text = Translation.Translate("\RUNNING")
    Interaction.ToggleStatusIcon(True)
    //......

위의 코드 예제를 보면 ToggleStatusIcon는 서브 프로시저로 값을 리턴하지 않습니다. 아래 쪽에서 ToggleStatusIcon를 호출하지만 호출 결과를 저장하거나 검사하는 로직은 존재하지 않습니다. 반면에 Translate는 함수로 사용되었습니다. "Function Translate..." 으로 정의한 함수 정의를 보면 변수 선언처럼 "As String"으로 함수의 데이터형을 선언하고 있고 아래쪽의 Translate를 호출한 곳에서도 Translate 호출 결과를 특정 변수에 저장하는 로직을 확인할 수 있습니다. 함수의 데이터 형은 리턴 값의 데이터 형을 의미하고 함수 내에서 Return 문을 통해서 전달하는 값의 데이터 형을 결정합니다. 물론 서브 프로시저는 데이터형도 없고 Return문이 올 수도 없습니다. 함수는 Return으로 값을 전달하면서 종료하는데 서브 프로시저를 중간에 나가려면 "Exit Sub"문을 사용합니다. 함수에서도 Exit Function을 사용할 수 있지만 이 경우 함수의 리턴값은 0이나 False, Nothing등 각 데이터 형별 기본값을 전달합니다.

서브 프로시저나 함수를 정의할 때는 위의 예제와 같이 괄호 안에 파라미터를 정의해서 전달 받을 자료의 데이터 형과 전달 방식등을 정의할 수 있습니다. 파라미터 정의는 변수 정의와 동일한 형태로 사용할 수 있으며 앞에 "ByVal" 또는 "ByRef"를 붙여서 파라미터 전달 방식을 조정할 수 있는데 ByVal은 파라미터를 값으로 전달한다는 의미로 일반적이 함수의 파라미터 전달 방식으로 이해할 수 있으며 ByRef를 붙이면 파라미터의 값을 보내는 것이 아니라 주소를 보내는 방식으로 C의 포인터 전달 방식으로 이해할 수 있습니다.  참조 방식으로 함수나 서브 프로시저에 파라미터를 넘기면 프로시저 내부에서 외부 변수를 직접 수정하는 것과 같은 효과를 낼 수 있습니다. 파라미터 정의 앞에 "Optional"을 붙이면 함수나 프로시저 호출시 해당 파라미터를 생략할 수 있다는 의미이며 생략한 경우에는 "=" 형태로 부여한 초기값이 기본값으로 입력됩니다. 위의 예제 코드에서도 DefaultValue에 기본값을 설정했습니다.

서브 프로시저의 정의는 Sub 이름(파라미터)......End Sub로 함수는 Function 이름(파라미터) As 데이터형......End Function의 형태로 정의할 수 있으며 다른 곳에서 함수나 서브 프로시저를 호출할 때는 이름(파라미터)의 형태로 사용합니다. 각 프로시저 내부에 선언한 변수는 지역변수라 하고 프로시저 외부에서 선언한 변수를 전역변수라 하며 전역변수는 모든 프로시저에서 접근할 수 있지만 지역 변수는 프로시저 외부에서는 사용할 수 없습니다.

Module Module1
    Dim Tot As Integer = 0
    Sub Main()
        Dim Tot As Integer = 0
        For I As Integer = 1 To 10
            Tot = Tot + AddTwo(I, I + 1)
        Next
        Console.WriteLine("Local Tot = " & Tot)
        Console.ReadLine()
    End Sub

    Function AddTwo(ByVal a As Integer, ByVal b As Integer) As Integer
        Tot = Tot + a
        Console.WriteLine("Global Tot = " & Tot)
        Return a + b
    End Function
End Module


위의 코드 예제와 실행 결과를 보면 프로시저 외부에 선언한 Tot는 모든 프로시저에서 접근 가능한 전역변수 이지만 Main 프로시저에 선언한 동일한 이름의 Tot변수 때문에 Main 프로시저 내부에서는 Tot를 사용하면 지역 변수에 접근하게 됩니다. AddTwo 함수에서 접근한 Tot는 전역변수입니다. 

프로시저 내부에 선언한 지역 변수는 초기값을 설정하거나 그렇지 않은 경우에도 호출될 때마다 새롭게 값이 설정되는 효과를 가져오는데 프로시저 내부에 설정한 변수값을 반복적으로 호출될 때도 지워지거나 초기값으로 돌아가지 않고 유지하고 싶을 경우에는 Dim 대신 Static을 변수 선언으로 사용하면 됩니다.

파라미터의 개수가 유동적일 경우에는 ParamArray를 파라미터 정의시 변수 앞에 기술하고 변수를 배열 형태로 정의하면 프로시저 호출시에 여러개의 유동적인 파라미터를 배열로 받을 수 있습니다. ParamArray 형태의 파라미터는 파라미터 정의의 맨 마지막 변수로 지정해야 합니다. 배열로 파라미터를 전달받는 대신 아래의 예제 코드와 같이 가능한 몇가지의 경우를 한정해서 동일한 이름의 각각의 프로시저를 정의해 놓고 사용하면 호출시에 파라미터 개수와 타입에 맞게 적절한 프로시저를 자동으로 호출해 줍니다. 이런 방식을 다형성(polymorphism) 이라 합니다.

    Public Function TranslateFormat(ByVal Code As String, ByVal Arg0 As Object) As String
        Return String.Format(Translate(Code), Arg0)
    End Function
    Public Function TranslateFormat(ByVal Code As String, ByVal Arg0 As Object, _
                                    ByVal Arg1 As Object) As String
        Return String.Format(Translate(Code), Arg0, Arg1)
    End Function
    Public Function TranslateFormat(ByVal Code As String, ByVal Arg0 As Object, _
                                    ByVal Arg1 As Object, ByVal Arg2 As Object) As String
        Return String.Format(Translate(Code), Arg0, Arg1, Arg2)
    End Function


※ 코드 참조 : http://synchronicity.sourceforge.net


댓글
댓글쓰기 폼