2

ラーニング パスのどこかで、このコードのセクションに出くわしました。ここで、作成者が「using」ブロックを使用して「ts」オブジェクトを作成しているにもかかわらず、using ブロック内で try catch ブロックを使用し、catch セクションで Dispose メソッドを明示的に呼び出してオブジェクト「ts」を破棄するという観察結果が 1 つあります。 . 不要だと感じます。「オブジェクトのみを破棄する」必要がある場合、ここで試してキャッチする必要がある理由がわかりません。

私の質問:

  1. ここで本当に try catch が必要ですか? この例では、どのような場合に役立ちますか?

  2. 「using」ブロックを使用する場合、この方法は正しいですか? GCプロセスのようにどのように反応しますか? そのオーバーヘッドの権利ですか?

どちらの質問も、初心者が理解できる方法で説明できれば幸いです。

using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew))
{
    try
    {
        ServiceReference1.Service1Client obj = new ServiceReference1.Service1Client();
        obj.UpdateData();
        ServiceReference2.Service1Client obj1 = new ServiceReference2.Service1Client();
        obj1.UpdateData();
        ts.Complete();
    }
    catch (Exception ex)
    {
        ts.Dispose();
    }
}
4

11 に答える 11

5

これは確かに私には不必要に思えます。usingステートメントは、コード ブロック全体をラップするブロックにコンパイルされ、finally例外がスローされるかどうかに関係なく実行されます。

本質的に、彼はこれを書いています:

TransactionScope ts;
try
{
    ts = new TransactionScope(TransactionScopeOption.RequiresNew);
    try
    {
        ServiceReference1.Service1Client obj = new ServiceReference1.Service1Client();
        obj.UpdateData();
        ServiceReference2.Service1Client obj1 = new ServiceReference2.Service1Client();
        obj1.UpdateData();
        ts.Complete();
    }
    catch (Exception ex)
    {
        ts.Dispose();
    }
}
finally
{
    ts.Dispose();
}

これは少しばかげています。彼が例外を完全に無視している (または「飲み込んでいる」) のは、特にばかげています99.99999993% の確率で、それは悪い考えです。

于 2013-03-01T20:03:27.987 に答える
1

簡単な答えはノーです。TransactionScopeはIDiposableを実装しているため、C#usingステートメントはコードブロックの実行後にDispose()を自動的に呼び出します。

このコンテキストでのtry/catchブロックの有用性は、一部のタイプの例外のトランザクションを完了する可能性があることです。

ほとんどの場合、ts.Complete();を呼び出すだけで十分です。usingブロックの最後のステートメントとして。これにより、前にスローされた例外によってトランザクションがロールバックされることが保証されます。

于 2013-03-01T20:10:27.690 に答える
1

私が理解していることから、Dispose電話の理由はありません。ただし、 には理由がありtry catchます。たとえば、UpdateData呼び出しが失敗した場合、いくつかの調整を行ってから再試行することができます。また、異なる例外を異なる方法で処理することもできます。catch ブロックがないと、それを行う機会がありません。

于 2013-03-01T20:03:53.250 に答える
1

ts.Dispose は、とにかく「using」を使用する場合、finally セクションで暗黙的に呼び出されます。ただし、例外をキャッチしない場合はスローされます。例のように、例外はcatchブロックによって静かに飲み込まれます。

于 2013-03-01T20:04:13.383 に答える
1

ステートメントの使用

using ステートメントを使用すると、オブジェクトのメソッドを呼び出しているときに例外が発生した場合でも、Dispose が確実に呼び出されます。オブジェクトを try ブロック内に配置してから、finally ブロックで Dispose を呼び出すことによって、同じ結果を得ることができます。実際、これは using ステートメントがコンパイラによってどのように変換されるかです。

そうです、投稿されたコードの例外ブロックで破棄することは不必要です。

于 2013-03-01T20:04:22.060 に答える
1

を介して定義されたオブジェクトは、 をusing実装する必要がありますIDisposable。そのオブジェクトは、ステートメント、 a 、 Exception など、何らかの手段Disposed()で範囲外 (制御がブロックを離れることを意味します) になるとすぐになります。したがって、変数が適切に破棄されるようにするために例外をキャッチすることは冗長です。usingreturngotousing

このコード:

using ( MyDisposableObject x = new MyDisposableObject() )
using ( AnotherDisposableObject y = new AnotherDisposableObject() )
{
  x.Foo() ;
  y.Bar( x ) ;
}

は、次のコードとまったく同じです。

MyDisposableObject x = new MyDisposableObject() ;
AnotherDisposableObject y = new AnotherDisposableObject() ;
try
{
  x.Foo() ;
  y.Bar( x ) ;
}
finally
{
  x.Dispose() ;
  y.Dispose() ;
}

ただし、usingブロック内で例外をキャッチする必要がある場合があります。その中で:

  • キャッチされた例外を実際に処理します。
  • キャッチされた例外のログ記録と再スロー。
  • たとえば、実行を継続できるようにするために、特定の例外を意図的に飲み込む。たとえば、何かを行うことが許可されているかどうかを確認するためにアクセス許可を要求する場合などです。要求が失敗すると、SecurityException がスローされます。たとえば、ユーザーが要求したファイルを開く権限がないことをユーザーに通知するなど、アクションを実行できるキャッチ。
于 2013-03-01T20:08:43.867 に答える
1

この特定のコード スニペットでは、catch 句が行う唯一のことは、例外が発生するのを防ぐことです。実際には、例外は無視されます。

ここでの dispose メソッドは、トランザクションをロールバックするために使用されますが、コードが using ブロックの外にある場合はいずれにしても dispose が呼び出されるため、不要なままです。

于 2013-03-01T20:02:56.157 に答える
1
  1. いいえ、ここでキャッチは必要ありません。
  2. 「このように」とは、ここで try/catch ブロックによって実装された二重破棄について言及していないことを前提としています。はい、これは適切な方法です (try/catch 部分を失います)。

コードがusingブロックを離れると、問題のオブジェクト (tsここでは) が破棄されます。オブジェクトを破棄せずにプログラムがこのブロックを離れることができる唯一の方法は、次の場合です。

  1. プログラムを殺す
  2. スレッドの終了

したがって、オブジェクトを正しく破棄するために try/catch 部分は必要ありません。

ただし、その try/catch コードが行うことは、try ブロック内のコード内の例外を飲み込むことです。ただし、dispose 呼び出しは不要です。

于 2013-03-01T20:03:52.850 に答える
0

1) 例外を実際に処理するか、ログに記録して再度スローする場合にのみ、try/catch が必要です。それ以外の try/catch の使用は、悪い習慣です。この場合、あなたがしているのは disposeだけなので、ブロックtsの中にいるので必要ありません。using

2) いいえ、dispose を呼び出す必要はありません。ブロックを使用すると、例外があっても処理されます。

于 2013-03-01T20:05:14.337 に答える
0

using ステートメント内で Dispose を呼び出す必要はありません。それはあなたのためにそれを扱います。

そこで処理したい例外がある場合、using 内で try catch を使用しても問題はありません。破棄しないでください。

于 2013-03-01T20:03:44.403 に答える
0

いいえ、その特定try..catchは完全に役に立ちません (少なくとも機能的には、遭遇する可能性のある例外を黙って食べます)。

これは同等ではないことに注意してください。using句は、単に a ではなくa にDispose展開されるため、成功した場合でも呼び出すため、より強力です。try..finallytry..catch

于 2013-03-01T20:03:44.550 に答える