[VB.NET] End の使用は信頼を裏切る

2013年12月11日

 VB には BASIC の時代から連綿と語り継がれている命令がありまして、End 命令もその一つ。しかしこの End 命令を安易に使うとひどい目にあう場合があります。

 たとえば最近の言語では例外機構が装備されていて、Finally ブロックは必ず実行すると信じられています。しかし、End 命令を使用すると Finally ブロックは実行されません。

Module Module1
    Sub Main()
        Try
            Console.WriteLine("終了")
            End

        Finally
            Console.WriteLine("ここは通らない")

        End Try
    End Sub
End Module

 End 命令は .net 的には Environment.Exit(0) で、C言語でいう exit(0); と等価です。プログラムがその場で中断されてしまいます。なのでパッと見た目正常にプロセスが落ちたように見えますが、いろいろな処理が抜け落ちてしまっている可能性があります。
 特に「Finally で後処理をしているから大丈夫」という前提を持つとき、誰かが End を使用すると、その前提が覆ってしまいます。つまり、Finally への信頼が裏切られてしまいます。
 また同様に、GUI 系では、プロセス(?)の終了イベントとして、MyApplication_Shutdown (WinForms) や Application_Exit (WPF) が用意されていますが、End を使用するとこのイベントが発生しません。この点も注意すべきポイントです。

 したがって、End 命令は安易に使うべきではありません。特に、プロセスが終了しないから End で終了させよう、というアプローチを行うと、後日死ぬ目を見ることがあるので注意です。


 ちなみに以下は End (Environment.Exit) を実行したときに通る箇所と通らない個所のまとめ。
 Finalizer は実行されますが、Dispose メソッドや Finally ブロックは実行されず、Thread も唐突に閉じられます。

Module Module1

    Sub Main()
        ' Newのみ
        Dim obj = New Class1

        ' ワーカースレッド起動
        Dim t = New System.Threading.Thread(AddressOf worker)
        t.Start()

        Try
            System.Threading.Thread.Sleep(1000)
            Console.WriteLine("終了")
            Environment.Exit(0) ' End 

        Finally
            Console.WriteLine("ここは通らない")

        End Try

    End Sub

    ' ワーカースレッド
    Sub worker()
        Try
            Console.WriteLine("スレッド実行中")
            ' 無限待ち
            System.Threading.Thread.Sleep(-1)

        Finally
            Console.WriteLine("ここは通らない")

        End Try

    End Sub
End Module

Class Class1
    Implements IDisposable

    ' ファイナライザー
    Protected Overrides Sub Finalize()
        Console.WriteLine("ここは通る")
    End Sub


#Region "IDisposable Support"
    ' IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        Console.WriteLine("ここは通らない")

    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

End Class





カテゴリー: Program, VB.NET

Follow comments via the RSS Feed | Leave a comment | Trackback URL

1 Comment to "[VB.NET] End の使用は信頼を裏切る"

  1. [VB.NET] Application.Exit の使用は期待を裏切る | オールトの雲

    [...]  「End の使用は信頼を裏切る」(http://ooltcloud.sakura.ne.jp/blog/201312/article_11223915.html)の続きエントリーです。 [...]

コメントを投稿する

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


«   »
 
Powered by Wordpress and MySQL. Theme by Shlomi Noach, openark.org