Visual Basic에서는 절차의 매개변수를 참조로 전달(ByRef)하거나 값으로 전달(ByVal)할 수 있습니다. 이는 절차 내에서의 변경 사항이 절차 외부의 원래 변수에 반영되는지 여부에 영향을 미칩니다.
질문 배경:
기본적으로 VB.NET에서 절차의 매개변수는 값으로 전달되며(ByVal), 이는 값의 복사가 이루어진다는 것을 의미합니다. ByRef를 통해 전달될 때는 복사가 아닌 원본 변수에 대한 참조가 전달됩니다.
문제:
잘못된 전달 방식의 사용은 오류를 발생시킬 수 있습니다. 예를 들어, ByRef를 잘못 사용하면 절차가 호출 코드의 변수를 의도치 않게 변경하거나, 반대로 변경 사항이 저장되지 않을 수 있습니다.
해결책:
ByRef는 여러 값을 반환하거나 전달된 변수를 변경해야 할 때 사용합니다. ByVal은 원하지 않는 변경을 방지하기 위해 나머지 경우에 사용합니다. ByRef는 반드시 필요할 때만 명시적으로 사용하는 것이 매우 중요합니다.
값으로 전달하는 것과 참조로 전달하는 예:
Sub DoubleValue(ByVal x As Integer) x = x * 2 End Sub Sub DoubleValueByRef(ByRef x As Integer) x = x * 2 End Sub Dim a As Integer = 5 DoubleValue(a) ' a는 여전히 5 DoubleValueByRef(a) ' a는 이제 10이 됩니다
주요 특징:
ByRef로 전달할 때 객체는 어떻게 될까요: 객체에 대한 참조가 변경되나요?
답변: 객체를 ByRef로 전달하고 절차 내에서 새로운 객체를 변수에 할당하면, 절차 외부의 원래 변수도 새로운 객체를 가리키게 됩니다. ByVal로 전달하면 객체의 속성을 변경할 수 있지만, 참조 자체를 재지정할 수는 없습니다 - 절차 외부의 변수는 이전 상태로 유지됩니다.
Sub ChangeRef(ByRef p As Person) p = New Person() With {.Name = "다른"} End Sub Sub ChangeVal(ByVal p As Person) p.Name = "변경됨" End Sub Dim pers As New Person With {.Name = "원본"} ChangeRef(pers) ' pers는 이제 새로운 객체 ChangeVal(pers) ' pers는 같은 객체, 이름이 변경됨
Return 값을 Function에서 ByRef로 사용할 수 있나요?
답변: 아니요, ByRef는 매개변수 전달 시에만 사용되고 함수의 반환 값에는 적용되지 않습니다.
ByVal로 배열 인수를 선언하면 배열의 내용을 변경할 수 있나요?
답변: 예, VB.NET에서 배열은 참조형이고 ByVal로 전달하더라도 참조가 복사되므로, 절차 내에서 배열의 요소를 변경할 수 있습니다.
팀의 한 개발자가 처리 알고리즘에서 ByRef를 사용했으며, 프로그램의 한 부분에서 값이 변경되면서 변수의 상태가 예상치 않게 변경되어 모듈이 정상적으로 작동하지 않게 되었습니다.
장점: 반환값의 구조를 명확히 하지 않고 데이터를 변경할 수 있음
단점: 예상치 못한 부작용의 높은 위험성, 버그 디버깅이 어려움
매개변수가 ByVal로 전달되고 여러 값을 반환하는 것은 반환되는 구조체 또는 Tuple을 통해 이루어져, 행동이 명확하고 편리하게 됩니다.
장점: 코드를 더 읽기 쉽고 유지 관리하기 쉽고 버그가 줄어듭니다.
단점: 때때로 추가적인 유형이나 구조체를 만들어야 할 필요가 있음