web-dev-qa-db-ja.com

「キャッチ」ブロックなしで「トライファイナル」ブロックを使用する

catchブロックなしでtry-finallyブロックを使用するのが適切な状況はありますか?

65
mkus

これを使用して、tryコンテンツの後または例外でいくつかのアクションが発生することを保証しますが、その例外を消費したくない場合に使用します。

明確にするために、これは例外を隠しません。 finallyブロックは、例外が呼び出しスタックに伝播される前に実行されます。

usingキーワードを使用する場合、これはtry-finallyにコンパイルされるため(不正確な変換ではありませんが、引数のために十分近いため)、誤って使用することもあります。

try
{
    TrySomeCodeThatMightException();
}
finally
{
    CleanupEvenOnFailure();
}

finallyで実行されるコードの実行は保証されませんが、保証されない場合はかなりエッジです-覚えていません。私が覚えているのは、その場合、finallyを実行しないことがあなたの最大の問題ではない可能性が非常に高いことです:-)基本的には汗をかかないでください。

Tobiasからの更新:finallyは、プロセスが強制終了されると実行されません。

Paddyからの更新:最終的に.net try..finallyブロックで実行されない場合の条件

最もよく見られる例は、コードが失敗した場合でも、データベース接続または外部リソースを破棄することです。

using (var conn = new SqlConnection("")) // Ignore the fact we likely use ORM ;-)
{
    // Do stuff.
}

次のようにsomethingにコンパイルします:

SqlConnection conn;

try
{
    conn = new SqlConnection("");
    // Do stuff.
}
finally
{
    if (conn != null)
        conn.Dispose();
}
101

usingtry-finallyと同等です。 finally内で何らかのクリーンアップを行い、例外を気にしない場合にのみ、try-finallyを使用します。

ベストアプローチ

try
{
   using(resource)
   {
       //Do something here
   }   
}catch(Exception)
{
     //Handle Error
}

usingによって呼び出されるクリーンアップも失敗しますが、コードは失敗しません。

finallyが実行されない条件がいくつかあります。

  • StackOverflowExceptionまたはExecutingEngineExceptionがある場合。
  • プロセスは外部ソースから強制終了されます。

これがあなたの疑問に答えることを願っています。

5
Amar Palsapure

たとえば、tryブロックで作成して使用するアンマネージリソースがある場合、finallyブロックを使用して、そのリソースを確実に解放できます。 finallyブロックは、tryブロックで何が起こっても(例外など)常に実行されます。

例えば。 lock(x)ステートメントは本当に:

System.Threading.Monitor.Enter(x); 
try { ... } 
finally 
{ 
    System.Threading.Monitor.Exit(x); 
} 

Finallyブロックは、排他ロックが確実に解放されるように常に呼び出されます。

3
Jeb

コードを使用した説明:

void MyMethod1()
{
    try
    {
        MyMethod2();
        MyMethod3();
    }
    catch(Exception e)
    {
        //do something with the exception
    }
}


void MyMethod2()
{
    try
    {
        //perform actions that need cleaning up
    }
    finally
    {
        //clean up
    }
}


void MyMethod3()
{
    //do something
}

MyMethod2またはMyMethod3のいずれかが例外をスローすると、MyMethod1によってキャッチされます。ただし、MyMethod2のコードはクリーンアップコードを実行する必要があります。例外がMyMethod1に渡される前に、データベース接続を閉じます。

http://forums.asp.net/t/1092267.aspx?Try+without+Catch+but+with+finally+doesn+t+throw+error+Why+no+syntax+error+

2
donstack

最後にtryを使用したい場合があります。通常はusingステートメントを使用しますが、リフレクションによってメソッドを呼び出しているため使用できません。

これは機能しません

using (objMsg  =  Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("omApp.MessagingBO")))
{

}

代わりに使用する

           object objMsg = null;
            try
            {
                objMsg
                   = Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("myAssembly.objBO"));

                strResponse = (string)objMsg.GetType().InvokeMember("MyMethod", BindingFlags.Public
                        | BindingFlags.Instance | BindingFlags.InvokeMethod, null, objMsg,
                        new object[] { vxmlRequest.OuterXml });
            }               
            finally
            {
                if (objMsg!=null)
                    ((IDisposable)objMsg).Dispose();
            }
1
jazza1000

どの例外がキャッチされたとしても、キャッチされなかったとしても、ブロックが終了する前にコードを実行したい場合は、finallyブロックが必要です。たとえば、開いているファイルを閉じたい場合があります。

関連項目 try-finally

1
IanNorton

try/finally:例外を処理したくないが、呼び出されたコードによって例外がスローされたかどうかにかかわらず、何らかのアクションが発生することを確認したい場合。

1
Mitch Wheat

次のリンクをご覧ください: https://softwareengineering.stackexchange.com/questions/131397/why-use-try-finally-without-a-catch-clause

それは、アプリケーションのアーキテクチャと、ブロックで実行する操作に依存します。

0
Harsh

これが私がいつも(ええと..)使用するユースケースです:

int? x; //note the nullable type here!
try
{
    x = int.Parse(someString);
}
catch { } //don't care, let it just be null
0
Alex

私はC#について何も知りませんが、try-finallyでできることは何でも、 sing statement でもっとエレガントにできると思われます。 C++には、最終的に RAIIの結果 がありません。

0
Neil G

1. catchなしでtryブロックを使用できますが、catch/finallyのいずれかを使用する必要があります。 2. tryブロックのみを使用することはできません。

0