29

これは本当に奇妙な問題です。複数の Catch ブロックを持つ Try Catch があります。最初の Catch ブロックにはコードがなく、コメントのみです。

Try
  'Some Code
Catch ex As ThreadAbortException
  'Do Nothing
Catch ex As Exception
  HandleException(ex)
End Try

ThreadAbortException 以外の例外がスローされた場合、予想どおり、2 番目の Catch によってキャッチされます。ただし、VS2010 でコードをステップ実行すると、ex オブジェクトは Nothing になります。これまでのところ、この問題を「修正」する方法は 2 つあります。

修正 1: 最初の例外変数の名前を変更します。

Try
  'Some Code
Catch tex As ThreadAbortException
  'Do Nothing
Catch ex As Exception
  HandleException(ex)
End Try

修正 2: 最初の Catch ブロックに任意のコード行を追加します。

Try
  'Some Code
Catch ex As ThreadAbortException
  Dim i As Integer = 1
Catch ex As Exception
  HandleException(ex)
End Try

上記のいずれの場合でも、HandleException のコードは、実行されても適切に機能するようです。これは Visual Studio またはデバッガーのバグですか? それとも、ここに何かが欠けていて、上記のコードの最初のブロックが無効なのでしょうか?

これはすべて .NET 4.0 で行われています。

4

3 に答える 3

18

Teejay は正しい答えを持っています。

ただし、Catchブロックが空の場合、この例外を処理しても意味がありません。最後のブロックがそれをキャッチするのを防ぎたいだけです。メソッドを使用できますが、空のCatchブロックを持つことは通常は受け入れられないことを考慮してください。例外をキャッチしないか、適切に処理する必要があります。それらを静かに飲み込むことはバグと見なされなければなりません。あなたのケースはこのルールの例外ですが、注意深いメンテナーを混乱させるため、コードで文書化する必要があります。

VB には、まさにこの状況のた​​めの特別なイディオムがあります。

Try
    ' …
Catch ex As Exception When Not TypeOf ex Is ThreadAbortException
    ' Only executed if `ex` isn’t a ThreadAbortException
End Try

このコードはまったくキャッチThreadAbortExceptionしません。これは、処理したくない場合に行うべき正しいことです。飲み込むThreadAbortException ことができないCatchため、キャッチしてもブロックの最後で再スローされます。

これは、従来のステートメントを使用する SysDragon の回答とは根本的に異なることに注意してください。Ifここでのコードでは、ステートメント内の特別な句をCatchフィルターとして使用しています。

于 2013-01-17T20:13:16.997 に答える
6

VSのデバッガーのバグのようです。

証拠

あなたが書く場合:

Try
    Throw New InvalidOperationException("MESSAGE")
Catch ex As ArgumentException
    'Do Nothing
Catch ex As Exception
    Debug.WriteLine(ex)
End Try

クイックウォッチモードexで評価さNothingれます

しかし

コンソールでは、プログラムは正しく印刷されますSystem.InvalidOperationException: MESSAGE

于 2013-01-17T16:16:39.760 に答える
-2

わかりました、詳しく説明しましょう...

キャッチごとに「結果」が必要なようです。特定のキャッチに対して何も起こらないようにしたい場合は、それを含めないか、コード内の別の場所に移動させます。

Try
   'Some Code
Catch ex As ThreadAbortException
   'Do something(ex: HandleExceptionSub())
Catch ex As Exception
   HandleException(ex)
End Try

例外を「キャッチ」した場合は、それを処理する必要があります。

編集:

また、try catch のしくみについて詳しく説明するのに役立つ次の情報も見つけました。

複数のキャッチ ブロック

try ブロックは、複数の catch ブロックを使用して処理できる複数の例外をスローできます。より特殊化された catch ブロックは、一般化されたブロックの前に来る必要があることに注意してください。そうしないと、コンパイラはコンパイル エラーを表示します。 複数のキャッチ ブロック

これはデバッガーの「バグ」ではありません。デバッガーは、すべての例外を見つけて処理するのに役立ちます。

編集:この例外は、別の投稿で読んだものから完全に回避できるようです。そして、例外を処理しないよりも、例外を回避した方がよいようです。 ThreadAbortException の処理

編集: try で複数の catch ブロックに関する詳細情報が見つかりました。これは MSDN からのもので、空の catch ブロックの後に catch ブロックが到達することはないと述べています... Try Catch finally ステートメント これはバグではなく、コード内のすべての例外の処理を強制するために期待される機能であることをさらに証明します。

編集: コメントで一部の人々をまっすぐに設定するために、これが本当にバグであるかどうかを確認するための非常に単純なテスト プログラムを作成しました。私の調査結果は、catch ブロックが完全に機能することです。複数の Catch ブロックを使用して Try Catch を作成する MSDN の文書化された方法に従うと、彼らが言うように機能するようです。

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            if (textBox1.Text == "")
            {
                throw new ArgumentNullException("textBox1", "TextBox can not be empty");
            }
            else
            {
                MyString(textBox1.Text);
            }
        }
        catch (ArgumentNullException ex)
        {
            //nothing
        }
        catch (Exception ex)
        {
            MessageBox.Show("Test: " + ex.Message);
        }
    }

    private int MyString(string text)
    {
        return int.Parse(text);
    }

ボタンとテキストボックスを備えた簡単なフォームを作成しました。テキストボックスが空の場合、ArgumentNullException をスローし、「MyString」で文字列を解析して整数に変換し、「FormatException」をスローします。「キャッチされた」例外を処理する正しい方法ではない空白のキャッチブロックを持つことは、実際には機能します。私が見る限り、これはバグではありません。どうやら私が Teejay と Konrad に同意できる唯一のことは、try catch メソッドを使用して ThreadAbortException をキャッチして処理することはできないということです。Konrad のソリューションは、try catch をコーディングするための最良の方法です。

于 2013-01-17T15:52:59.367 に答える