方法: プロシージャ引数の値が変更されないように保護する (Visual Basic)

Visual Basic では、プロシージャでパラメーターが ByRef として宣言されている場合、引数の基になる呼び出し元のコードのプログラミング要素への直接参照がプロシージャ コードに渡されます。 これにより、プロシージャは引数の基になる呼び出し元のコードの値を変更できます。 呼び出し元のコードで、そのような変更から保護することが必要な場合もあります。

プロシージャで対応するパラメーターを ByVal として宣言することで、引数を変更から常に保護できます。 特定の引数を一部のケースでは変更できるようにし、他のケースでは変更できないようにする場合は、その引数を ByRef として宣言し、呼び出し元のコードが呼び出しごとに引渡し方法を決定できるようにします。 これを行うには、対応する引数をかっこで囲んで値渡しにするか、かっこで囲まずに参照渡しにします。 詳細については、方法: 引数の値渡しを強制する」をご覧ください。

次の例は、配列変数を受け取り、その要素を操作する 2 つのプロシージャを示しています。 increase プロシージャは、各要素に 1 を加算するだけです。 replace プロシージャは、a() パラメーターに新しい配列を割り当ててから、各要素に 1 を加算します。 ただし、再割り当ては、呼び出し元のコードの基になる配列変数には影響しません。

Public Sub increase(ByVal a() As Long)
    For j As Integer = 0 To UBound(a)
        a(j) = a(j) + 1
    Next j
End Sub
Public Sub replace(ByVal a() As Long)
    Dim k() As Long = {100, 200, 300}
    a = k
    For j As Integer = 0 To UBound(a)
        a(j) = a(j) + 1
    Next j
End Sub
Dim n() As Long = {10, 20, 30, 40}
Call increase(n)
MsgBox("After increase(n): " & CStr(n(0)) & ", " & 
    CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))
Call replace(n)
MsgBox("After replace(n): " & CStr(n(0)) & ", " & 
    CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))

最初の MsgBox 呼び出しでは、"After increase(n): 11, 21, 31, 41" と表示されます。 配列 n は参照型であるため、引渡し方法が ByVal であっても、increase はそのメンバーを変更できます。

2 番目の MsgBox 呼び出しでは、"After replace(n): 11, 21, 31, 41" と表示されます。 nByVal で渡されるため、replace は呼び出し元のコードの変数 n に新しい配列を割り当てて変更することはできません。 replace が新しい配列インスタンス k を作成し、ローカル変数 a に割り当てると、呼び出し元のコードによって渡された n への参照は失われます。 a のメンバーを変更すると、ローカル配列 k だけが影響を受けます。 したがって、replace は呼び出し元のコードの配列 n の値をインクリメントしません。

コードのコンパイル

Visual Basic の既定では、引数は値渡しになります。 ただし、宣言されるすべてのパラメーターに、ByVal または ByRef キーワードを含めることをお勧めします。 これにより、コードが読みやすくなります。

関連項目