4

データベース接続を開くなど、リソースを集中的に使用する操作のベスト プラクティスに関するコンセンサスは、Usingブロックを使用することであるUsingようです。.

私が見つけたほとんどの例は次のように書かれています。

Sub ExecuteCommand(ByVal sql As String, ByVal connectionString As String)
    Using connection As New SqlConnection(connectionString)
        Dim command As New SqlCommand(sql, connection)
        command.Connection.Open()
        command.ExecuteNonQuery()
    End Using
End Sub

ただし、ネストされたUsingブロックは許可されており、上記が次のように記述されているのを時折 (ただしめったに) 見ません。

Sub ExecuteCommand(ByVal sql As String, ByVal connectionString As String)
    Using connection As New SqlConnection(connectionString)
        Using command As New SqlCommand(sql, connection)
            command.Connection.Open()
            command.ExecuteNonQuery()
        End Using
    End Using
End Sub

私の質問: 複数のネストされたUsingブロックに利点はありますか? それとも、単一の Using ブロックは、含まれているすべてのリソースが破棄されることを既に保証していますか?

(注: 私のコードは VB.NET ですが、同じ質問が C# にも当てはまります。)

4

5 に答える 5

10

using ブロックは、「リソースの破棄を保証します...未処理の例外が発生した場合でも」。

その「保証」を一粒の塩で取ってください。多くのことがリソースの処分を妨げる可能性があります。using ブロックに無限ループが含まれている場合はどうなりますか? または、ブロックが例外をスローし、スタックの上位にある敵対的な例外フィルターが無限ループに入り、using ステートメントに関連付けられた finally ブロックに制御を戻さない? それとも、ブロックは Environment.FailFast を呼び出しますか? ディスポーザルの実行を妨げるものはたくさんあります。 正確さを処分に依存するようなプログラムは絶対に書かないでください。処分は礼儀正しさのためにあり、希少なリソースをプールに戻し、他の人がそれらを使用できるようにします。

さらに、この点が明確であることを確認させてください。真に未処理の例外は、C# の実装定義の動作です。ブロックのusingfinally 句は、例外が using ブロック内でスローされ、別の場所で処理される状況を処理するためにあります。例外がブロック内でスローされ、決して処理されない状況を処理するためではありません。扱いました。それが発生した場合、何が起こるかを決定するのは完全に実装次第です。C# 言語は、決して処理されない例外をスローするプログラムの動作について、まったく保証しません。リソースが破棄される可能性があります。そうではないかもしれません。あなたは予期せず取り壊されようとしている建物にいます。食器を洗ってきれいに片付けるのに本当に時間を費やしたいですか?

複数のネストされた Using ブロックに利点はありますか?

はい。

単一の Using ブロックは、含まれているすべてのリソースが破棄されることを既に保証していますか?

いいえ。 using ステートメントで実際に言及されているリソースのみがクリーンアップされます。そのため、それらをネストします。

内側のリソースが外側のリソースと同じリソースを解放する責任を負うため、技術的にそうする必要がない場合がいくつかあります。しかし、ブロックを使用して入れ子にすることは何も害を及ぼすものではなく、何が起こっているのかを読者に非常に明確にします。ここでのベスト プラクティスは、クリーンアップするリソースごとに 1 つの using ステートメントを用意することです。

于 2013-10-04T18:30:25.703 に答える
7

ネストされたusingブロックは間違いなく便利です。単一のブロックはDispose、同じブロック内で開かれる可能性のある他の変数ではなく、独自の変数でのみ呼び出されます。そのため、プログラム内の定義されたポイントでクリーンアップする各変数 (実装する型のすべての変数である必要がありますIDisposable) には、独自のusingブロックが必要です。

于 2013-10-04T18:25:49.413 に答える
1

ネストされたusingステートメントは非常に便利です。SqlCommandただし、多くのプログラマーは、オブジェクトにリソースのクリーンアップが必要であるとは考えていません。つまり、リソースはコマンドではなく接続です。

追加した

SqlCommand には Close() メソッドがないため、SqlCommand に Dispose() メソッドがあっても、Close() メソッドがないということは、実際には「閉じる/解放するものがない」ことを示しています。使い捨て可能なインスタンスは、最終的には常に Disposed になります。ソースを掘り下げずに信頼できるものを見つけるのは難しいですが、この記事で MS の担当者は、それが何を破棄したのかを正確に尋ねられたとき、「実際にはそれほど多くはありません...」と述べ、SqlCommand() の USING 句を提案し続けました。 、そのため、質問に正しく答えましたが、最初はその背後にあるあいまいさを避けました.

于 2013-10-04T18:28:46.203 に答える