종종 초보들이 어려워 하는 부분 중 하나는 매개변수의 전달방식이라는 것이 있습니다.
전달방식이 하나라면 혼동될 일이 없을텐데 말입니다. 매개변수의 전달방식은 값에 의한 전달(Call by
Value), 참조에 의한 전달(Call by Reference)이 있습니다.
다음의 글은 예전
MOD모임의 정상석님이 올려둔 글에 제가 몇 가지 뱀 다리(蛇足)를 넣어 둔 것입니다. 뱀과 뱀 다리를
소화시켜서 내 것으로 만드시길 바랍니다.
[뱀]
요즘 보고 있는 책에 내용이 있어서 적어봅니다.
언제 ByVal 또는 ByRef를 사용해야
하는지?
- 매개 변수를 통해 프로시저 내부로 전달된 변수들을 변경할
필요가 없다면 ByVal을 사용한다.
- 매개 변수를 통해 프로시저 내부로 전달된 변수들을 변경할 필요가 있다면 ByRef를
사용한다.
- 어떤 것을 사용해야 할지 잘 모르는 경우에는 ByVal 키워드를 사용한다.
- VBA는 기본적으로 ByRef를 사용한다. (VB.net에서는 기본적으로 ByVal을 사용)
ex.
Sub Main()
MyValue = 10
Call ProcessFile(MyValue)
MsgBox MyValue
End Sub
1. ByVal인 경우
Sub ProcessFile(ByVal YourValue)
YourValue = YourValue * 10 'YourValue = 100,
MyValue = 10
End Sub
2. ByRef인 경우
Sub ProcessFile(ByRef YourValue)
YourValue = YourValue * 10 'YourValue = 100,
MyValue = 100
End Sub
|
[뱀 다리]
종종 서브프로시저를 호출할 때 전달방식과 관련하여 에러메시지를 볼 것입니다.
"ByRef인수형식이 일치하지 않습니다." 라는...
이는 전달하려는 값의
데이터 형과 전달 받으려는 서브프로시저의 매개변수의
데이터 형이 다르기 때문입니다. 가령 다음과 같은 프로시져는
에러가 납니다.
Sub Main()
Dim i As Integer
i = 100
Proc i
End Sub
Sub Proc(i As Long)
Debug.Print i
End Sub
Main에서는 integer형 값을 Proc에 넘겨
주려
합니다.
그러나 Proc에서는 long값만 받죠. 이때 넘겨주는 것은 ByRef이므로 변수의 값이 아니라
변수의 주소입니다.
VB에서 값은 자동적으로 형변환(캐스팅)되지만 주소는 그런게
없습니다. 따라서 에러가 납니다. 그러므로 두 데이터형중 하나로 통일하거나 또는 전달방식을ByVal로
바꿔야 합니다.
|
추가로 전달방식과 관련하여
오래된 얘기이지만 몇 가지 추가 사항(뱀 꼬리)이 있습니다. 먼저
다음과 같은 프로시저를 봅시다.
[뱀 꼬리]
Sub CallByCallRef()
arg1 = 5
arg2 = 6
mysub arg1, arg2 '// call by
reference
Debug.Print arg1, arg2 '// results in 1 and 2
arg1 = 5
arg2 = 6
mysub (arg1), (arg2) '// call by value
Debug.Print arg1, arg2 '// results in 5 and 6
End Sub
Sub mysub(arg1, arg2)
arg1 = 1
arg2 = 2
End Sub
|
위의
mysub프로시저에서는 기본적인 값 전달방식을 참조방식으로 했습니다. 그래서 mysub arg1,
arg2와 같이 호출하면 arg1과 arg2의 값은 5, 6에서 1, 2로 바뀝니다.
그런데 두 번째 호출에서는
mysub라는 프로시저에 매개변수를 넘기면서 각각의 매개변수에 괄호를 둘러치고 넘깁니다.
이렇게 하면 mysub프로시저에서 기본적인 값 전달방식을 참조방식으로 지정했지만 값에 의한 전달방식으로
바뀌게 됩니다.
그래서 결국
arg1은 5가 그대로 출력되고 arg2 역시 mysub에 영향을 받지
아니하고 6을 가지고 있게 됩니다.
|