VBA初心者が「ByRef」を使うときに陥りやすい罠をまとめました。参照渡しは便利ですが、「呼び出し元の変数が勝手に書き換わる」という性質があるため、意図しない副作用が起きやすいです。
1. デフォルトが ByRef 問題
- 罠: 引数に何も指定しないと自動的に ByRef になる。
- 例:
Sub AddFive(n As Integer) ' ← ByRef 扱い
n = n + 5
End Sub
Sub Test()
Dim x As Integer
x = 10
AddFive x
Debug.Print x ' → 15(意図せず書き換わる)
End Sub
VB- 解説: 「戻り値を返すつもりがないのに変数が変わる」ことが初心者の混乱ポイント。安全のために必ず ByVal を明示する習慣をつける。
2. 複数の呼び出しで値が壊れる
- 罠: 同じ変数を複数のプロシージャに渡すと、どこで書き換えられたか分からなくなる。
- 例:
Sub UpdateAll()
Dim msg As String
msg = "Hello"
AppendWorld msg
AppendExclamation msg
Debug.Print msg ' → "Hello World!!!"
End Sub
VB- 解説: 呼び出し先がどんどん書き換えるため、「元の値がどこで変わったか」追えなくなる。
3. 配列の構造変更(ReDim/Erase)
- 罠: ByRef で渡した配列を
ReDimやEraseすると、呼び出し元の配列も消える。 - 例:
Sub ClearArray(ByRef arr() As Long)
Erase arr
End Sub
VB- 解説: 呼び出し元の配列が突然消えるため、後続処理でエラーになる。配列の構造変更は戻り値で新しい配列を返す方が安全。
4. オブジェクト参照の付け替え
- 罠: Range や Worksheet を ByRef で渡して
Setし直すと、呼び出し元の参照も変わる。 - 例:
Sub MoveRange(ByRef r As Range)
Set r = r.Offset(1, 0)
End Sub
VB- 解説: 呼び出し元の変数が意図せず別セルを指すようになる。「中身を変える」処理と「参照を変える」処理を混同しやすい。
5. Nothing の代入で参照が消える
- 罠: ByRef で渡したオブジェクトに
Set obj = Nothingすると、呼び出し元の参照も消える。 - 例:
Sub KillRange(ByRef r As Range)
Set r = Nothing
End Sub
VB- 解説: 呼び出し元で
r.Valueを使おうとするとエラー。参照破棄は呼び出し元に影響するため危険。
6. 意図しない副作用でデバッグ困難
- 罠: ByRef の副作用で「どこで値が変わったか」分からなくなる。
- 例: 複数のモジュールで同じ変数を渡し回すと、値が予期せず変わる。
- 解説: デバッグ時に「どこで壊れたか」追跡が難しい。副作用を減らすために ByVal を基本にする。
7. 関数の戻り値と混同
- 罠: ByRef で値を返す設計にすると、関数の戻り値と二重で返すことになり混乱。
- 解説: 「戻り値は1つ、複数返したいなら ByRef」というルールを守らないとコードが読みにくくなる。
✅ 安全に使うための指針
- 基本は ByVal:副作用を避ける。
- ByRef は「複数値を返したいとき」や「参照を意図的に差し替えたいとき」だけ。
- オブジェクトや配列は特に注意:中身の変更と参照の付け替えを区別する。
- 必ずコメントで意図を明示:「この引数は呼び出し元を書き換える」と書いておくと安心。
