15

2 つの異なるアセンブリに次の 2 つのクラスがあるとします。

//in assembly A
public class TypeA {
   // Constructor omitted
   public void MethodA
   {
     try {
       //do something
     }
     catch {
        throw;
     }
   }
}
//in assembly B
public class TypeB {
   public void MethodB
   {
     try {
       TypeA a = new TypeA();
       a.MethodA();
     }
     catch (Exception e)
       //Handle exception
     }
   }
}

この場合、MethodA の try-catch は例外を昇格させるだけで、実際には処理しません。MethodA で try-catch を使用する利点はありますか? つまり、この種の try-catch ブロックとまったく使用しないことの間に違いはありますか?

4

11 に答える 11

7

あなたの例では、これには利点がありません。しかし、特定の例外をバブルアップすることが望ましい場合もあります。

    public void Foo()
    {
        try
        {
            // Some service adapter code

            // A call to the service
        }
        catch (ServiceBoundaryException)
        {
            throw;
        }
        catch (Exception ex)
        {
            throw new AdapterBoundaryException("some message", ex);
        }
    }

これにより、例外が発生した境界を簡単に特定できます。この場合、境界例外が境界に固有のコードに対してのみスローされるようにする必要があります。

于 2009-04-04T18:14:40.157 に答える
3

MethodA 用に記述した方法でコードを使用すると、違いはありません。プロセッササイクルを食い尽くすだけです。ただし、解放しなければならないリソースがある場合は、この方法でコードを作成する利点があります。例えば

Resource r = GetSomeResource();
try {
  // Do Something
} catch { 
  FreeSomeResource();
  throw;
}
FreeSomeResource();

ただし、この方法で実行しても意味がありません。代わりに、finally ブロックを使用する方 がはるかに優れています。

于 2009-04-04T17:46:00.847 に答える
3

はい、違いがあります。例外をキャッチすると、.NET は何らかの方法で例外を処理すると想定し、キャッチを実行している関数までスタックが巻き戻されます。

キャッチしないと、未処理の例外として終了し、何らかの診断 (デバッガーや例外ロガーなど) が呼び出され、実際の障害点での完全なスタックとその状態が検査に使用されます。

したがって、他の場所で処理されない例外をキャッチしてから再スローすると、実際に何が起こったのかについての本当に有用な情報を診断ツールから奪うことになります。

于 2009-04-04T17:51:53.813 に答える
2

投げ直すだけでは意味がありません。何もしていないのと同じです。

ただし、実際に何かを行うと便利になります。最も一般的なのは、例外をログに記録することです。クラスの状態を変更することもできます。

于 2009-04-04T17:48:55.850 に答える
2

そのままでは、最初のオプションは悪い (または「役に立たない」べきか?) アイデアのように思えます。ただし、この方法で行われることはほとんどありません。例外は、通常、次の 2 つの条件の下で Catch ブロック内から再スローされます。

を。データに対して生成された例外を確認し、条件付きでスタックにバブルアップします。

try 
{
  //do something
}
catch (Exception ex)
{
  //Check ex for certain conditions.
  if (ex.Message = "Something bad")
    throw ex;
  else
    //Handle the exception here itself.
}

b. コンポーネント内で容認できない状態が発生したため、この情報を呼び出し元のコードに伝える必要があります (通常、他の有用な情報を追加するか、別の例外の種類でまとめてラップします)。

try 
{
  //do something
}
catch (StackOverflowException ex)
{
    //Bubble up the exception to calling code 
    //by wrapping it up in a custom exception.
    throw new MyEuphemisticException(ex, "Something not-so-good just happened!");
}
于 2009-04-04T18:15:00.387 に答える
1

クラスは 2 つの異なるアセンブリにあるため、単に例外をキャッチしてログに記録し、それを呼び出し元にスローして、適切と思われる方法で処理できるようにすることができます。throw ex の代わりに throw を使用すると、例外の発生場所に関するコンテキスト情報が保持されます。これは、アセンブリが API/フレームワークであり、意味がない限り例外を飲み込んではならない場合に役立ちますが、EventLog などに記録されている場合はトラブルシューティングに役立ちます。

于 2009-04-04T21:58:19.570 に答える
1

オプション A を実行しないでください。Anton が言うように、スタック トレースを使い果たします。JaredPar の例も、スタックトレースを消費します。より良い解決策は次のとおりです。

SomeType* pValue = GetValue();
try {
  // Do Something
} finally {
  delete pValue;
}

FileStream など、C# でリリースする必要があるものがある場合は、次の 2 つの選択肢があります。

FileStream stream;
try
{
  stream = new FileStream("C:\\afile.txt");
  // do something with the stream
}
finally
{
  // Will always close the stream, even if there are an exception
  stream.Close(); 
}

またはよりきれいに:

using (FileStream stream = new FileStream("c:\\afile.txt"))
{
  // do something with the stream
}

Using ステートメントは、完了時または例外が閉じられたときにストリームを破棄 (および閉じます) します。

于 2009-04-04T17:55:51.090 に答える
1

キャッチして投げると、throwラインにブレークポイントを設定できます。

于 2009-04-04T17:58:36.090 に答える
1

例外の再スローを使用して、次のような一般的な例外にカプセル化できます...次の例を検討してください。

public class XmlException: Exception{
   ....
} 

public class XmlParser{
   public void Parse()
   {
      try{
          ....
      }
      catch(IOException ex)
      {
         throw new XmlException("IO Error while Parsing", ex );
      }
   }
}

これは、例外を分類するよりも利点があります。これは、aspx ファイル ハンドラーと他の多くのシステム コードが、スタックまでの道のりとロジックの流れを決定する例外のカプセル化を行う方法です。

于 2009-04-04T17:58:56.793 に答える
1

アセンブリ A - try catch - ブロックは私には意味がありません。例外を処理しないのであれば、なぜそれらの例外をキャッチするのでしょうか.. とにかく次のレベルにスローされます。

ただし、中間層 API などを作成していて、その層で例外を処理する (したがって、例外を消費する) ことが意味をなさない場合は、独自の層 ApplicationException をスローできます。しかし、確かに同じ例外を再スローしても意味がありません。

于 2009-04-04T19:47:16.283 に答える