引数の値渡しと参照渡し (Visual Basic)

Visual Basic では、プロシージャに引数を渡すときに、"" 渡しまたは "参照" 渡しにすることができます。 これは "引渡し方法" と呼ばれ、引数の基になる呼び出し元のコードのプログラミング要素をプロシージャが変更できるかどうかを決定します。 プロシージャの宣言で ByVal または ByRef キーワードを指定することによって、各パラメーターの引渡し方法を決定します。

相違点

プロシージャに引数を渡すときは、相互作用するいくつかの相違点に注意してください。

  • 基になるプログラミング要素が変更可能か変更不可能か

  • 引数自体が変更可能か変更不可能か

  • 引数が値渡しか参照渡しか

  • 引数のデータ型が値型か参照型か

詳細については、「Differences Between Modifiable and Nonmodifiable Arguments (変更できる引数と変更できない引数の違い)」および「Differences Between Passing an Argument By Value and By Reference (引数の値渡しと参照渡しの違い)」をご覧ください。

引渡し方法の選択

引数ごとに引渡し方法を慎重に選択する必要があります。

  • 保護。 2 つの引渡し方法のいずれかを選択する際に、最も重要な基準は、呼び出し元の変数が変更の影響を受けるかどうかです。 引数を ByRef で渡す利点は、プロシージャがその引数を使用して呼び出し元のコードに値を返すことができることです。 引数を ByVal で渡す利点は、プロシージャによって変更されないように変数を保護することです。

  • パフォーマンス。 引渡し方法はコードのパフォーマンスに影響を与える可能性がありますが、通常、その違いはわずかです。 唯一の例外は、ByVal で渡される値型です。 この場合、Visual Basic では引数のデータ コンテンツ全体をコピーします。 そのため、構造体などの大きな値型の場合、ByRef で渡す方が効率的です。

    参照型の場合、データへのポインターだけがコピーされます (32 ビット プラットフォームでは 4 バイト、64 ビット プラットフォームでは 8 バイト)。 そのため、パフォーマンスを損なうことなく、String または Object 型の引数を値渡しにすることができます。

引渡し方法の決定

プロシージャの宣言で、各パラメーターの引渡し方法を指定します。 呼び出し元のコードは、引渡し方法 ByVal をオーバーライドできません。

パラメーターが ByRef で宣言されている場合、呼び出し元のコードは、呼び出しで引数名をかっこで囲むことによって、引渡し方法を強制的に ByVal にすることができます。 詳細については、方法: 引数の値渡しを強制する」をご覧ください。

Visual Basic の既定では、引数は値渡しになります。

引数を値渡しにする場合

  • 引数の基になる呼び出し元のコードの要素が変更不可能な要素である場合は、対応するパラメーターを ByVal で宣言します。 コードは、変更不可能な要素の値を変更することはできません。

  • 基になる要素が変更可能であっても、プロシージャがその値を変更できないようにする場合は、パラメーターを ByVal で宣言します。 値渡しされた変更可能な要素の値を変更できるのは、呼び出し元のコードだけです。

引数を参照渡しにする場合

  • プロシージャが呼び出し元のコードの基になる要素を変更する必要がある場合は、対応するパラメーターを ByRef で宣言します。

  • コードを正しく実行するには、呼び出し元のコードの基になる要素をプロシージャが変更する必要がある場合は、パラメーターを ByRef で宣言します。 値渡しにした場合や、呼び出し元のコードで引数をかっこで囲むことによって引渡し方法 ByRef をオーバーライドした場合、プロシージャ呼び出しによって予期しない結果が生じる可能性があります。

説明

次の例は、引数を値渡しにする場合と参照渡しにする場合を示しています。 Calculate プロシージャには、ByVal パラメーターと ByRef パラメーターの両方があります。 このプロシージャのタスクは、指定された rate (金利) と debt (合計金額) を使用して、debt の新しい値を計算することです。これは、debt の元の値に金利を適用した結果です。 debtByRef パラメーターであるため、新しい合計は、debt に対応する呼び出し元のコードの引数の値に反映されます。 Calculate が値を変更しないようにする必要があるため、rate パラメーターは ByVal パラメーターです。

コード

Module Module1

    Sub Main()
        ' Two interest rates are declared, one a constant and one a 
        ' variable.
        Const highRate As Double = 12.5
        Dim lowRate = highRate * 0.6

        Dim initialDebt = 4999.99
        ' Make a copy of the original value of the debt.
        Dim debtWithInterest = initialDebt

        ' Calculate the total debt with the high interest rate applied.
        ' Argument highRate is a constant, which is appropriate for a 
        ' ByVal parameter. Argument debtWithInterest must be a variable
        ' because the procedure will change its value to the calculated
        ' total with interest applied.
        Calculate(highRate, debtWithInterest)
        ' Format the result to represent currency, and display it.
        Dim debtString = Format(debtWithInterest, "C")
        Console.WriteLine("What I owe with high interest: " & debtString)

        ' Repeat the process with lowRate. Argument lowRate is not a 
        ' constant, but the ByVal parameter protects it from accidental
        ' or intentional change by the procedure. 

        ' Set debtWithInterest back to the original value.
        debtWithInterest = initialDebt
        Calculate(lowRate, debtWithInterest)
        debtString = Format(debtWithInterest, "C")
        Console.WriteLine("What I owe with low interest:  " & debtString)
    End Sub

    ' Parameter rate is a ByVal parameter because the procedure should
    ' not change the value of the corresponding argument in the 
    ' calling code. 

    ' The calculated value of the debt parameter, however, should be
    ' reflected in the value of the corresponding argument in the 
    ' calling code. Therefore, it must be declared ByRef. 
    Sub Calculate(ByVal rate As Double, ByRef debt As Double)
        debt = debt + (debt * rate / 100)
    End Sub

End Module

関連項目