ByValとByRefについて


1、ByValとByRefについて
 1−1、基本型の場合
 1−2、オブジェクト型の場合


1、ByValとByRefについて

1−1、基本型の場合

 ByValとは元の変数のコピーを渡す方法です。
 コピーを渡すので、メソッド(プロジージャ)の中でその値を変更しても、呼び出しもとの変数は変更されません。

 引数をByRefとすると、メソッド(プロジージャ)の中でその値を変更すると、呼び出しもとの変数の値も変更されます。

例1(引数の型が基本型の場合):サンプルコードはここ(ファイル名: ByValAndByRef_P1.xls)。
Main
Sub Main()
    Dim a As Long
    Dim b As Long
    a = 1
    b = 1
    Call Sub_ByVal(a)
    Call Sub_ByRef(b)
    Debug.Print "a=" & a
    Debug.Print "b=" & b
End Sub

Sub_ByVal
Sub Sub_ByVal(ByVal x As Long)
    x = 2
End Sub

Sub_ByRef
Sub Sub_ByRef(ByRef x As Long)
    x = 2
End Sub

Mainメ ソッドの実行結果
([イミディエイト]ウインドウへの出力結果)
a=1
b=2

Mainメソッドの変数aはByValで値を渡したので、Sub_ByValメソッド実行後も値が変化しない。
Mainメソッドの変数bはByRefで値を渡したので、Sub_ByRefメソッド実行後はSub_ByRefメソッド内で変更した値となった。

このページのトップへ


1−2、オブジェクト型の場合

 引数にオブジェクトを渡す場合も基本型の場合と同じです。
 オブジェクト型というのは変数が保持している値がオブジェクトの先頭アドレス(4バイト)なので、ByValで値を渡すということはその先頭アドレスの コピーが渡されるという事になります。コピーを渡すので、メソッド(プロジージャ)内で参照先を変更しても(先頭アドレスを変更しても)、もとの変数には 影響しません。(例2)
 また、ByValでオブジェクトを渡した場合でも、そのオブジェクトのプロパティ値を変更した場合はもとの変数が参照していたオブジェクトのプロパ ティ値は変更されます。(例3)
 
まとめると以下のようになります。

オブジェクト 型をByValで渡した場合
オブジェクト 型をByRefで渡した場合
メソッド(プ ロジージャ)内で
参照先のオブジェクトの
プロパティ値を変えると
もとの変数が参照していたオブジェクトの
プロパティ値も変化している(例3)
もとの変数が参照していたオブジェクトの
プロパティ値も変化している(例3)
メソッド(プ ロジージャ)内で
参照先のオブジェクトを
変えると
もとの変数は
メソッド(プロシージャ)実行前に
参照していたオブジェクトと変わらない。(例2)
もとの変数の参照先オブジェクトは
メソッド(プロシージャ)内で変更した
オブジェクトとなる(例2)



例2(引数がオブジェクト型で、メソッド内で参照先を変更した場合):サンプルコードはこ こ(ファイル名:ByValAndByRef_O2.xls)。
Main
Sub Main()
    Dim a As Collection
    Dim b As Collection
    Set a = New Collection
    Set b = New Collection
    Call Sub_ByVal(a)
    Call Sub_ByRef(b)
    Debug.Print "a is Nothong? " & (a Is Nothing)
    Debug.Print "b is Nothong? " & (b Is Nothing)
End Sub

Sub_ByVal
Sub Sub_ByVal(ByVal x As Collection)
    Set x = Nothing
End Sub

Sub_ByRef
Sub Sub_ByRef(ByRef x As Collection)
    Set x = Nothing
End Sub

Mainメ ソッドの実行結果
([イミディエイト]ウインドウへの出力結果)
a is Nothong? False
b is Nothong? True

Mainメソッドの変数aはByValで値を渡したので、Sub_ByValメソッド実行後も参照先が変化しない。
Mainメソッドの変数bはByRefで値を渡したので、Sub_ByRefメソッド実行後はSub_ByRefメソッド内で変更した参照先 (Nothing:どのオブジェクトも参照していないことを表す)となった。


例3(引数がオブジェクト型で、メソッド内でプロパティを変更した場合):サンプルコードはここ(ファイル名: ByValAndByRef_O3.xls)。
Main
Sub Main()
    Dim a As Collection
    Dim b As Collection
    Set a = New Collection
    Set b = New Collection
    Debug.Print "メソッドを実行する前"
    Debug.Print "a.Count=" & (a.Count)
    Debug.Print "b.Count=" & (b.Count)
    Call Sub_ByVal(a)
    Call Sub_ByRef(b)
    Debug.Print "メソッドを実行した後"
    Debug.Print "a.Count=" & (a.Count)
    Debug.Print "b.Count=" & (b.Count)
End Sub

Sub_ByVal
Sub Sub_ByVal(ByVal x As Collection)
    Call x.Add("abcdefg")
End Sub

Sub_ByRef
Sub Sub_ByRef(ByRef x As Collection)
    Call x.Add("abcdefg")
End Sub

Mainメ ソッドの実行結果
([イミディエイト]ウインドウへの出力結果)
メソッドを実行する前
a.Count=0
b.Count=0
メソッドを実行した後
a.Count=1
b.Count=1

ByVal、ByRefのときもメソッド実行後はCountプロパティの値が変化した。
このページのトップへ