じゃんぬねっと日誌

ネタと雑記と時々プログラミング

目次

Blog 利用状況

ニュース

Halo3 にハマり中。アービターかわいいよ。あーびたん。

スポンサードリンク

運営サイト

  • C# と VB.NET の入門サイト

Blog Item

フィードメーター - じゃんぬねっと日誌

書庫

VB6.0 で「Form の既定のインスタンス」を防ぐには?

VB6.0 (Visual Basic 6.0) では、Form そのものの「型」を、実体 (インスタンス) のように扱えてしまいます。たとえば、下記コードの Form2 は、ある Form の「型」であるのにも関わらず、直接 Show メソッドを呼び出せてしまいます。

VB6.0 - フォームの「既定のインスタンス」を利用

'/** Form1 クラス */
Option Explicit

' CommandButton1 をクリックすると Form2 が表示される
Private Sub Command1_Click()
    Call Form2.Show
End Sub

これは、Form2 という「型」と同名の「既定のインスタンス」があるという考え方で良いでしょう。つまり、Form2 という型にアクセスするだけで、同名のグローバルな 'Form2' が、暗黙的にインスタンス化されるということです。

暗黙的にインスタンス化された「既定のインスタンス」は、アプリケーション内全体でアクセス可能な、単一のインスタンスです。

Form2 という型で直接アクセスしようとした時に、VB が勝手にインスタンス化 (暗黙的にインスタンス化) をしています。実際、Form2 内に含まれるメンバを呼び出すと、Form2 は Initialize イベント (コンストラクタ) が実行されます。

さて、Form2 は「型」に過ぎませんから、本来は次のように「インスタンス (実体)」を生成して、そのインスタンスから Show メソッドを呼び出します。

VB6.0 - 明示的にフォームのインスタンスを生成

'/** Form1 クラス */
Option Explicit

' CommandButton1 をクリックすると Form2 が表示される
Private Sub Command1_Click()
    Dim f2 As Form2
    Set f2 = New Form2

    Call f2.Show
End Sub

まず、インスタンスを生成して f2 に参照として Set しています。その後、f2 に含まれるインスタンスから Show メソッドを呼び出しています。

このような、正当な方法を利用するメリットはいくつかあります。

  • インスタンスを生成することで、初期化が保証される
  • スコープを狭めることができる (例のコードでは Command1_Click プロシージャ内でのみ有効)
  • 結果、他の場所から勝手に呼び出されてしまう心配がない
  • 外部のどこから操作されているのか明確になる
  • 別のインスタンスを作って複製可能

既定のインスタンス (暗黙的なインスタンス化) を使用すると、上記のメリットとは逆の結果になります。

  • 初期化されないので (微少の) パフォーマンス向上になる (場合もある)
  • どこからでも呼び出せるので場合によっては楽 (スパゲティになることもある)
  • ソースの記述量が減り、簡素化されている (ように見える)

では、既定のインスタンス (暗黙的なインスタンス化) を、防ぐにはどうすれば良いのでしょう? 既定のインスタンスが最初に使用される時は、前述したように「Initialize イベント (コンストラクタ)」が実行されます。これを、うまく利用できないかと思いついたのがこちらの方法。

VB6.0 - 既定のインスタンスの使用 (暗黙的なインスタンス化) を防ぐ

'/** Form2 クラス */
Option Explicit

' コンストラクタ
Private Sub Form_Initialize()
    Set Form2 = Nothing
End Sub

上記のように、インスタンス化されたところで、とっとと参照を解放してしまうのです。この状態で、既定のインスタンスを利用しようとすると、

実行時エラー '91':

オブジェクト変数または With ブロック変数が設定されていません。

という実行時エラーが起こります。参照がないから当たり前ですよね。

グループ開発でルールを守らない方がいても、これなら安心です。仮に、Form2 のコンストラクタをコメントアウトしても、誰がコメントアウトしたのかは VSS でわかります。

さて、困ったことに、VB8 (VB2005) で、既定のインスタンス (暗黙的なインスタンス化) が復活してしまいました。VB2005 については、また明日にでも書こうと思います。

制限するためのオプションが何故ないのかと、小 1 時間(ry

投稿日時 : 2006年10月25日 10:08

コメントを追加

# re: VB6.0 で Form の「既定のインスタンス」(暗黙のインスタンス化) を防ぐには? 2006/10/25 10:20 未記入

>困ったことに、VB8 (VB2005) で、既定のインスタンス (暗黙のインスタンス化) が復活してしまいました。

私も驚きました。
Moduleも属性で表現されていたので、この動作も属性で実装されていないか心配です。
もし属性で実装されているのなら、リフレクションによりパフォーマンス劣化してしまうので、パフォーマンスが悪い言語になってしまいますね・・・
困ったものだ。

# re: VB6.0 で Form の「既定のインスタンス」(暗黙のインスタンス化) を防ぐには? 2006/10/25 16:12 こじこじ

VB2005での回避方法って何かないんでしょうか?

# VB2005 で Form の「既定のインスタンス」(暗黙のインスタンス化) を防ぐには? 2006/10/26 9:45 じゃんぬねっと日誌

VB2005 で Form の「既定のインスタンス」(暗黙のインスタンス化) を防ぐには?

# re: VB6.0 で Form の「既定のインスタンス」(暗黙のインスタンス化) を防ぐには? 2006/10/26 12:35 じゃんぬ

回避方法を書いてみました。

# 複数のフォーム間で、データをやりとりする 2006/11/21 23:39 何となく Blog by Jitta

複数のフォーム間で、データをやりとりする

タイトル  
名前  
URL
コメント