web-dev-qa-db-ja.com

{}ステートメントを使用して内部でreturnを呼び出すのは良い方法ですか?

returnブロック内でusingを呼び出すのが安全/優れたアプローチかどうかを知りたいだけです。

例えば.

_using(var scope = new TransactionScope())
{
  // my core logic
  return true; // if condition met else
  return false;
  scope.Complete();
}
_

最後に最も中括弧dispose()が呼び出されることを知っています。しかし、returnは与えられたスコープ(AFAIK)からコントロールをジャンプするので、上記の場合はどうなるでしょう...

  1. scope.Complete()が呼び出されますか?
  2. そのため、スコープのdispose()メソッドに対して。
78
user240141

Usingブロックは_try/finally_ブロックにすぎないため、returnブロック内でusingを呼び出すことは完全に安全です。

上記の例では、return trueの後、スコープは破棄され、値が返されます。 _return false_、およびscope.Complete()notが呼び出されます。ただし、Disposeは、finallyブロック内にあるため、呼び出されます。

あなたのコードは本質的にこれと同じです(それが理解しやすくする場合):

_var scope = new TransactionScope())
try
{
  // my core logic
  return true; // if condition met else
  return false;
  scope.Complete();
}
finally
{
  if( scope != null) 
    ((IDisposable)scope).Dispose();
}
_

トランザクションをコミットするためにscope.Complete()に到達する方法がないため、トランザクションはnever commitすることに注意してください。

120

それは問題ありません-finally句(using句の閉じ中かっこが内部で行うこと)は、どのようにスコープが去っても常に実行されます。

ただし、これはfinallyブロック(usingを使用する場合は明示的に設定できない)にあるステートメントにのみ当てはまります。したがって、あなたの例では、scope.Complete()が呼び出されることはありません(コンパイラーが到達不能コードについて警告することを期待しています)。

6
Lucero

scope.Completeは、returnの前に必ず呼び出す必要があります。コンパイラは警告を表示し、このコードは呼び出されません。

return自体について-はい、usingステートメント内で呼び出しても安全です。を使用して、舞台裏で最終的にブロックし、最終的にブロックを実行するように変換します。

2
Tony Kh

一般的に、これは良いアプローチです。ただし、あなたの場合、scope.Complete()を呼び出す前に戻ると、TransactionScopeが破棄されます。デザインに依存します。

そのため、このサンプルでは、​​Complete()は呼び出されず、IDisposableインターフェイスを継承していると想定してスコープが破棄されます。

2
M. Mennan Kara

scope.Complete()が確実に呼び出されるようにするには、try/finallyでラップします。 disposeは、代替のtry/finallyブロックであるusingでラップしているために呼び出されます。

using(var scope = new TransactionScope())
{
  try
  {
  // my core logic
  return true; // if condition met else
  return false;
  }
  finally
  {
   scope.Complete();
  }
}
1
Aristos

指定した例には問題があります。 scope.Complete()は呼び出されません。第二に、returnステートメント内でusingステートメントを使用することはお勧めできません。以下を参照してください。

using(var scope = new TransactionScope())
{
    //have some logic here
    return scope;      
}

この単純な例では、ポイントはそれです。ステートメントの使用が終了すると、scopeの値はnullになります。

したがって、ステートメントを使用して内部に戻らない方が良いでしょう。

1
daryal

この例では、scope.Complete()は実行されません。ただし、returnコマンドは、スタックに割り当てられているすべてのものをクリーンアップします。 GCは、参照されていないすべてを処理します。したがって、GCで取得できないオブジェクトがない限り、問題はありません。

0
ThunderGr