なぜC#で最終的に使用するのですか?


194

最終的にブロック内にあるものはすべて(ほぼ)常に実行されるので、コードを囲むことと閉じないままにすることの違いは何ですか?


3
閉じないままにしておくとはどういう意味ですか?
ラメッシュ

5
そして、「(ほぼ)」とはどういう意味ですか?
ベスカ

49
マシンがtry句を実行しているときに電源コードを抜くと、finally句は呼び出されません。
Dour High Arch

5
笑、はい、それは本当です、しかしあなたは本当にそれのためにコーディングすることができませんか?
Ed S.

2
@Ed:トランザクションを使用します。try句は、finally句の単一のアトミックな変更で永続化できる、ある種の一時的またはメモリ内の変更を行う必要があります。これはめったに簡単ではなく、特別なハードウェアが必要になる場合があります。
Dour High Arch

回答:


412

例外があるかどうかに関係なく、finallyブロック内のコードが実行されます。これは、接続を閉じるように常に実行する必要がある特定のハウスキーピング機能に関しては非常に便利です。

今、私は推測しますが、この操作を行う必要がありますなぜ、あなたの質問は次のとおりです。

try
{
    doSomething();
}
catch
{
    catchSomething();
}
finally
{
    alwaysDoThis();
}

あなたがこれを行うことができるとき:

try
{
    doSomething();
}
catch
{
    catchSomething();
}

alwaysDoThis();

答えは、多くの場合、catchステートメント内のコードが例外を再スローするか、現在の関数から抜け出すことです。後者のコードでは、「alwaysDoThis();」catchステートメント内のコードがreturnを発行するか、新しい例外をスローした場合、呼び出しは実行されません。


3
うーん。私が言ったことと非常に似ていますが、より明確でより正確です。確かに+1。
beska

48
これは、try {}ブロック内の「return」にも当てはまります。
ルーカス

5
実際、catch {}ブロックがなくても適用されます(試行/最後に、例外をバブルアップさせます)
Lucas

私よりもましで、仕事をしていて、詳細に答えるのに10分も費やしたくありませんでした。+1
マットブリッグス

2
はい、これはまさに私が考えていたものでした:D今私はそれを理解しています。
ロドリゴ

62

try-finallyを使用することのほとんどの利点はすでに指摘されていますが、私はこれを追加すると思いました:

try
{
    // Code here that might throw an exception...

    if (arbitraryCondition)
    {
        return true;
    }

    // Code here that might throw an exception...
}
finally
{
    // Code here gets executed regardless of whether "return true;" was called within the try block (i.e. regardless of the value of arbitraryCondition).
}

この動作は、さまざまな状況で、特にクリーンアップ(リソースの破棄)を実行する必要がある場合に非常に役立ちますが、この場合はブロックを使用する方がよい場合がよくあります。


2
これが文字通り私が最終的に使用する唯一の理由です
Christopher Townsend

12

ストリームリーダー、dbリクエストなどのアンマネージコードリクエストを使用するときはいつでも。例外をキャッチし、try catchを使用して、最後にストリーム、データリーダーなどを閉じます。エラーが発生したときに接続が閉じられない場合、これはdbリクエストでは非常に悪いです。

 SqlConnection myConn = new SqlConnection("Connectionstring");
        try
        {
            myConn.Open();
            //make na DB Request                
        }
        catch (Exception DBException)
        {
            //do somehting with exception
        }
        finally
        {
           myConn.Close();
           myConn.Dispose();
        }

エラーをキャッチしたくない場合は、

 using (SqlConnection myConn = new SqlConnection("Connectionstring"))
        {
            myConn.Open();
            //make na DB Request
            myConn.Close();
        }

エラーが発生した場合、接続オブジェクトは自動的に破棄されますが、エラーはキャプチャされません


2
Dispose()は接続もClose()するので、両方を呼び出す必要はありません。Close()はDipose()ではなく、接続を再開できます。
ルーカス

ニース、使用について言及してくれてありがとう。そうでなければ、私は答えなければならないでしょう。
ダンローゼンスターク2009


8

最後に、ステートメントは戻った後でも実行できます。

private int myfun()
{
    int a = 100; //any number
    int b = 0;
    try
    {
        a = (5 / b);
        return a;
    }
    catch (Exception ex)
    {
        Response.Write(ex.Message);
        return a;
    }

 //   Response.Write("Statement after return before finally");  -->this will give error "Syntax error, 'try' expected"
    finally
    {
      Response.Write("Statement after return in finally"); // --> This will execute , even after having return code above
    } 

    Response.Write("Statement after return after finally");  // -->Unreachable code
}

7

finally、のように:

try {
  // do something risky
} catch (Exception ex) {
  // handle an exception
} finally {
  // do any required cleanup
}

try..catchtryブロックが例外をスローしたかどうかに関係なく、ブロックの後にコードを実行する機会が保証されています。

これにより、リソース、データベース接続、ファイルハンドルなどの解放などに最適です。


3
これらの例はすべて、通常、usingブロックを使用した方が適切ですが、それでも回答が損なわれることはありません。
Joel Coehoorn 2009

4

ファイルリーダーの例外を使用してfinallyの使用法を説明します例

  • 最終的に使用せず
try{

  StreamReader strReader = new StreamReader(@"C:\Ariven\Project\Data.txt");
  Console.WriteLine(strReader.ReadeToEnd());
  StreamReader.Close();
}
catch (Exception ex)
{
  Console.WriteLine(ex.Message);
}

場合は、上記の例では、ファイルと呼ばれるDATA.TXTが不足している、例外がスローされ、処理されますが、声明と呼ばれるが、StreamReader.Close();実行されることはありません。
このため、リーダーに関連するリソースはリリースされませんでした。

  • 上記の問題を解決するために、最終的に使用します
StreamReader strReader = null;
try{
    strReader = new StreamReader(@"C:\Ariven\Project\Data.txt");
    Console.WriteLine(strReader.ReadeToEnd());
}
catch (Exception ex){
    Console.WriteLine(ex.Message);
}
finally{
    if (strReader != null){
        StreamReader.Close();
    }
}

ハッピーコーディング:)

注: 「@」は、「認識されないエスケープシーケンス」のエラーを回避するために、逐語的な文字列を作成するために使用されます。@記号は、その文字列を文字通りに読み取ることを意味し、それ以外の場合は制御文字を解釈しません。


2

待機中(砂時計)カーソルではなく、カーソルをデフォルトのポインタに戻す必要があるとします。カーソルを設定する前に例外がスローされ、アプリが完全にクラッシュしない場合は、混乱するカーソルが残る可能性があります。


2

例外(catchブロックなし)を処理したくないが、クリーンアップコードを実行したい場合があります。

例えば:

try
{
    // exception (or not)
}
finally
{
    // clean up always
}

例外がキャッチされない場合、finallyブロックの実行は、オペレーティングシステムが例外アンワインド操作のトリガーを選択したかどうかによって異なります。
Vikas Verma 2014

2

finishブロックは、tryブロックに割り当てられたリソースをクリーンアップしたり、例外が発生した場合でも実行する必要のあるコードを実行したりするのに役立ちます。tryブロックの終了方法に関係なく、制御は常にfinallyブロックに渡されます。


1

ああ...あなたの言っていることがわかると思います!ちょっと時間がかかりました...「finallyブロックの後ではなくfinallyブロックに配置し、try-catch-finallyの完全に外側に配置するのはなぜですか」と疑問に思っています。

例として、エラーをスローした場合に実行を停止しているが、開いているファイルやデータベース接続などのリソースをクリーンアップしたいことが原因である可能性があります。


1

Finalブロックの制御フローは、TryまたはCatchブロックの後にあります。

[1. First Code]
[2. Try]
[3. Catch]
[4. Finally]
[5. After Code]

例外1> 2> 3> 4> 5(3にReturnステートメントがある場合)1> 2> 3> 4

例外なし1> 2> 4> 5(2にreturnステートメントがある場合)1> 2> 4


0

ドキュメントに記載されているように

catchとfinallyを一緒に使用する一般的な使用法は、tryブロックでリソースを取得して使用し、catchブロックで例外的な状況に対処し、finallyブロックでリソースを解放することです。

これを読むことも価値があります、それは述べています:

一致するcatch句が見つかると、システムは制御をcatch句の最初のステートメントに移す準備をします。catch句の実行が始まる前に、システムはまず、例外をキャッチしたものよりもネストされたtryステートメントに関連付けられたfinally句を順番に実行します。

したがってfinally、前のcatch節にreturnステートメントがあったとしても、節に存在するコードが実行されることは明らかです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.