10

「使用する」のポイントは、オブジェクトのDisposeメソッドが呼び出されることを保証することであると理解しています。しかし、「using」ステートメント内の例外はどのように処理する必要がありますか?例外がある場合は、「using」ステートメントをtrycatchでラップする必要があります。例えば:


usingパラメータ内のオブジェクトの作成で作成された例外があるとしましょう

 try
 {
    // Exception in using parameter
    using (SqlConnection connection = new SqlConnection("LippertTheLeopard"))
    {
       connection.Open();
    }
 }
 catch (Exception ex)
 {

 }

またはusingスコープ内の例外

 using (SqlConnection connection = new SqlConnection())
 {
    try
    {
       connection.Open();
    }
    catch (Exception ex)
    {

    }
 }

すでにtrycatchで例外を処理する必要がある場合は、オブジェクトの破棄も処理する必要があるようです。この場合、「using」ステートメントはまったく役に立たないようです。「using」ステートメントで例外を適切に処理するにはどうすればよいですか?私が見逃しているこれへのより良いアプローチはありますか?

 SqlConnection connection2 = null;
 try
 {
    connection2 = new SqlConnection("z");
    connection2.Open();
 }
 catch (Exception ex)
 {

 }
 finally
 {
    IDisposable disp = connection2 as IDisposable;
    if (disp != null)
    {
       disp.Dispose();
    }
 }

「using」キーワードの構文はもう少し甘くなります
か...これがあるといいでしょう:

 using (SqlConnection connection = new SqlConnection())
 {
    connection.Open();
 }
 catch(Exception ex)
 {
   // What went wrong? Well at least connection is Disposed
 }
4

8 に答える 8

27

無関係なキーワード内に余分な機能を「隠している」からです。

ただし、いつでもこのように書くことができます

using (...) try
{
}
catch (...)
{
}

そして、このように行はあなたの意図を表しています - トライでもある using ステートメント

于 2009-11-12T20:01:00.930 に答える
12

usingエラー処理とは関係ありません。「このブロックを離れるときに Dispose を呼び出す」の省略形です。2番目のコード例は完全に受け入れられます...なぜ機能するものを台無しにするのですか?

于 2009-11-12T19:58:45.313 に答える
8

using ブロックは、try-finally ブロックのシンタックス シュガーにすぎません。catch 句が必要な場合は、try-catch-finally を使用してください。

SqlConnection connection;
try 
{
    connection = new SqlConnection();
    connection.Open();
}
catch(Exception ex)
{
    // handle
}
finally 
{
    if (connection != null)
    {
        connection.Dispose();
    }
}

はい、これは理論上の「using-catch」よりも多くのコードです。私は、言語開発者がこれを非常に優先度が高いとは考えていなかったと判断しており、その損失を感じたことはないとは言えません。

于 2009-11-12T20:00:28.247 に答える
5

これが役立つ場所がありました。しかし、多くの場合、これを実行しようとすると、設計に問題があることが判明します。間違った場所で例外を処理しようとしています。

代わりに、次のレベルに進むことができるようにする必要があります。つまり、このコードをすぐに呼び出すのではなく、このコードを呼び出した関数で処理します。

于 2009-11-12T20:00:59.400 に答える
2

興味深いアイデアですが、次のような混乱を招く可能性があります。

 using (SqlConnection connection = new SqlConnection())
 using (SqlCommand cmd = new SqlCommand())
 {
     connection.Open();
 }
 catch(Exception ex)
 {
     // Is connection valid? Is cmd valid?  how would you tell?
     // if the ctor of either throw do I get here?
 }
于 2009-11-12T19:59:39.247 に答える
2

私の意見では、あなたは懸念を混合しています。リソース管理 (つまり、オブジェクトの破棄) は、例外処理から完全に分離されています。質問で説明する1対1のマッピングは、非常に特殊なケースです。通常、例外処理は、using スコープが終了するのと同じ場所では発生しません。または、using ブロック内に複数の try-catch 領域がある場合もあります。または ...

于 2009-11-12T20:02:58.087 に答える
0

例1と例2を組み合わせて使用​​することをお勧めします。その理由は、たとえば、usingステートメントがファイルを読み取り、例外をスローする可能性があるためです(つまり、ファイルが見つかりません)。キャッチしない場合は、未処理の例外があります。try catchブロックをusingブロック内に配置すると、usingステートメントの実行後に発生する例外のみがキャッチされます。あなたの例1と2の組み合わせが最良の私見です。

于 2009-11-12T20:05:38.440 に答える
0

「using」ステートメントの目的は、実行がコードのブロックを終了するときに、その終了がフォールスルー、例外、またはのいずれを経由するかに関係なく、ある種のクリーンアップ操作が確実に行われるようにすることですreturn。ブロックがこれらの手段のいずれかを介して終了するとDispose、のパラメーターが呼び出されますusing。ブロックは、ある意味で、パラメーターとして指定されているものすべての利益のために存在し、using一般に、ブロックが終了した理由は関係ありません。

規定が役立つ可能性のある珍しいケースがいくつかあります。usingそれらの追加の有用性のレベルは、そもそも持っていることによって提供されるレベルをはるかに下回ります(ただし、実装者が提供するのに適していると考える他のいくつかの機能よりも間違いなく優れています)。

(1)他のオブジェクトをカプセル化するオブジェクトのコンストラクターまたはファクトリには、非常に一般的なパターンがありIDisposableます。コンストラクターまたはファクトリが例外を介して終了する場合、カプセル化されたオブジェクトはDisposedである必要がありますが、それらを介しreturnて終了する場合はそうではありません。現在、このような動作は/を介して、または/をフラグと組み合わせて実装する必要がありtryますがcatch、例外を介して終了したときにのみ呼び出されるバリエーションがある場合、またはステートメントがnullになる場合は、IMHOが役立ちます。廃棄が必要なオブジェクトを保持するためにステートメントによって一時的に使用されます(識別子を前に付けることはできないため、このような機能は、やや類似した方法で追加できます)。tryfinallyusingDisposekeep usingusingusingyield return

(2)場合によっては、キーワードが引数finallyを受け入れるように拡張されていると便利です。Exception保護された句が終了する原因となった例外(存在する場合)、またはnull保護された句が正常に終了する場合(リターンまたはフォールスルーを介して)、およびusingブロックがinterface IDisposeExOnly {void DisposeEx(Exception ex);}andを使用できる場合Interface IDisposeEx : IDisposable, IDisposableExOnly {}(コンパイル時に選択されたDisposeEx()場合)実装、またはDispose()その他)。これにより、トランザクションベースのオブジェクトが自動コミットを安全にサポートできるようになり(つまり、渡された例外がの場合はコミットを実行し、nullnull以外の場合はロールバックを実行できます)Dispose、保護された条項内の問題(適切なことはDispose呼び出されたときに保留されていた例外と、結果として発生した例外の両方をカプセル化する例外をスローしますが、現在、それを行うためのクリーンな方法はありません)。

Microsoftがそのような機能を追加するかどうかはわかりません。最初の部分と2番目の部分の最初の部分は、完全に言語レベルで処理されます。2番目の後半は、フレームワークレベルになります。

于 2012-07-30T15:08:13.843 に答える