引数の値渡しと参照渡し (Visual Basic)
Visual Basic では、値渡しまたは参照渡しで引数をプロシージャに渡すことができます。 これは引渡し方法と呼ばれ、引数の基となる、呼び出し元のコードのプログラミング要素をプロシージャが変更できるかどうかが決まります。 プロシージャの宣言では、ByVal (Visual Basic) または ByRef (Visual Basic) キーワードを指定することで、各パラメーターの引き渡し方法を決定します。
違い
引数をプロシージャに渡す場合、2 つの引き渡し方法の違いに注意してください。
基になるプログラミング要素が変更可能か変更不可能か
引数自体が変更可能か変更不可能か
引数が値渡しか参照渡しか
引数のデータ型が値型か参照型か
詳細については、「変更できる引数と変更できない引数の違い (Visual Basic)」および「引数の値渡しと参照渡しの違い (Visual Basic)」を参照してください。
引数渡しの方法の選択
各引数の引き渡し方法は慎重に決定してください。
保護。 引数を渡す方法を選択するときに最も重要な基準となるのは、呼び出し元のコードの変数を変更できるようにするかどうかです。 ByRef で引数を渡す場合の利点は、プロシージャから呼び出し元のコードに引数を通じて値を返すことができるという点にあります。 一方、ByVal を使用する利点は、プロシージャによって変数が変更されるのを防ぐことができるという点にあります。
パフォーマンス。 どちらの方法を使用するかによってコードのパフォーマンスが変わってきますが、その差は一般にごくわずかです。 ただし、値型を ByVal で渡す場合は例外です。 この場合、Visual Basic では、引数の内容がすべてコピーされます。 このため、構造体などの大きな値型では、ByRef で渡す方が効率的です。
参照型では、データへのポインターだけがコピーされます (32 ビット プラットフォームでは 4 バイト、64 ビット プラットフォームでは 8 バイト)。 したがって、パフォーマンスを損なうことなく、String 型や Object 型の引数を値で渡すことができます。
引数渡しの方法の決定
プロシージャの宣言では、各パラメーターの引き渡し方法を指定します。 呼び出し元のコードは ByVal 機構をオーバーライドすることはできません。
パラメーターが ByRefで宣言されている場合は、呼び出し元のコードは ByVal の呼び出しで引数名をかっこで囲むことによって機構ができます。 詳細については、「方法: 引数の値渡しを強制する (Visual Basic)」を参照してください。
Visual Basic の既定の設定では、値渡しで引数が渡されます。
値渡しで引数を渡す場合
引数の基になる呼び出し元のコード要素が変更不可能である場合は、これに対応するパラメーターは ByVal (Visual Basic) で宣言します。 変更不可能な要素の値は、どのようなコードでも変更できません。
基になる要素が変更可能であっても、プロシージャからはその値を変更できないようにするには、パラメーターを ByVal で宣言します。 変更可能な要素が値渡しされた場合、その値を変更できるのは呼び出し元のコードだけです。
参照渡しで引数を渡す場合
プロシージャが、呼び出し元のコード内にある基になる要素を変更する必要が本当にある場合、対応するパラメーターを ByRef (Visual Basic) で宣言します。
プロシージャが正しく実行されるかどうかが、呼び出し元のコード内の基になる要素を変更するプロシージャに依存する場合、パラメーターを ByRef で宣言します。 これを値渡しした場合、または、呼び出し元のコードが引数をかっこで囲んで ByRef の引き渡し方法をオーバーライドした場合、プロシージャは予期しない結果になることがあります。
例
説明
値渡しで引数を渡す場合と参照渡しで引数を渡す場合の例を次に示します。 プロシージャ Calculate には、ByVal パラメーターと ByRef パラメーターの両方があります。 このプロシージャのタスクは、指定された利率 (rate) と総額 (debt) に基づいて、debt の元の値に利率を適用して debt の新しい値を計算することです。 debt は ByRef パラメーターであるため、新しい総額は、debt に対応する呼び出し元コードの引数の値に反映されます。 rate の値は Calculate で変更されないため、このパラメーターは 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
参照
処理手順
方法: プロシージャに引数を渡す (Visual Basic)
方法: プロシージャ引数の値を変更する (Visual Basic)
方法: プロシージャ引数の値が変化しないようにする (Visual Basic)
方法: 引数の値渡しを強制する (Visual Basic)