プログラミング言語の経験者がVBAに触れた際、しばしば激しい混乱に陥るポイントがあります。それが、C#インデックス範囲外例外との違いです。
モダンな言語であるC#では、配列のインデックスは厳格に「0始まり(ゼロオリジン)」と定められており、範囲外アクセス時には明確にIndexOutOfRangeExceptionという例外が送出されます。一方、VBAは1990年代からの後方互換性を引き継いでおり、極めて柔軟である反面、仕様が多重化しています。
例えば、シート上のセル範囲をまとめて配列変数に代入した場合(arr = Range("A1:C5").Value)、生成される2次元配列のインデックスは「1始まり」になります。ところが、Split関数で文字列を分割して生成された配列は「0始まり」です。さらにモジュール先頭にOption Base 1を宣言すれば全体の挙動が変わり、ユーザー定義の動的配列では負のインデックスすら設定可能です。
この「始まりの数値が文脈によって揺らぐ」というVBA特有の構造こそが、開発者の脳に過負荷をかけ、エラー9を量産させる元凶です。また、ユーザーフォーム開発で見られるListBoxインデックス範囲外エラーも同様の設計差から生じます。リストボックスの項目が未選択の場合、ListIndexプロパティは「-1」という特殊な数値を返します。この戻り値の検証を挟まずにListBox1.List(ListBox1.ListIndex)と要素を直接参照しようとすると、存在しない「-1番目の部屋」を覗くことになり、エラー9が確実に炸裂します。