6

Webリクエストの「using」ステートメント内に「try/catch」を埋め込んでも大丈夫ですか?私のコードは正しいですか?それが私の要件です:

  1. 「using」ステートメントを使用して、HttpWebResponseのリソースがどのような場合でも解放されることを確認したい

    • ただし、HttpWebResponseと "response =(HttpWebResponse)request.GetResponse();"に関する例外がある場合は、カスタム処理を実行する必要があります。特に。

私のソースコード:

        var result = new HttpHeaderInfo();
        HttpWebRequest request = null;
        HttpWebResponse response = null;
        using (response)
        {
            try
            {
                request = (HttpWebRequest)WebRequest.Create(uri);
                request.Method = "HEAD";
                request.KeepAlive = false;
                request.Timeout = Properties.Settings.Default.WebTimeoutDefault;

                response = (HttpWebResponse)request.GetResponse();
                result.LastModified = response.LastModified;
                result.ContentType = response.ContentType;
                result.StatusCode = response.StatusCode;
                result.ContentLength = response.ContentLength;
            }
            catch (Exception ex)
            {
                if (ex is InvalidOperationException ||
                    ex is ProtocolViolationException ||
                    ex is WebException)
                {
                    result.HttpError = ex;
                    result.LastModified = System.DateTime.MinValue;
                    result.ContentType = null;
                }
                else { throw; }
            }

        }

ありがとう

4

3 に答える 3

11

それは問題ありませんが、少し冗長です。一般的な意味では、ブロックを簡単に削除し、 の後にusingブロックを追加して、そこに明示的に呼び出すことができます。これにより、コードのネストが削減されます。finallycatchDispose

より具体的な意味で、私を少し悩ませているのは、ブロックresponseに入るまで実際に代入しないことです。明示的な変数宣言は不要であり、このコンテキストでは混乱します。私はそれを次のように書き直します:using

HttpHeaderInfo result;
try
{
    var request = (HttpWebRequest)WebRequest.Create(uri);
    request.Method = "HEAD";
    request.KeepAlive = false;
    request.Timeout = Properties.Settings.Default.WebTimeoutDefault;

    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {
        result = new HttpHeaderInfo();
        result.LastModified = response.LastModified;
        result.ContentType = response.ContentType;
        result.StatusCode = response.StatusCode;
        result.ContentLength = response.ContentLength;
    }
}
catch (WebException ex)
{
    // etc.
}

これは、元のフォームよりもはるかに明確です。WebExceptionまた、ジェネリックではなく、キャッチしていることにも注意してくださいSystem.Exception。一般的な例外をキャッチしてからそのタイプをチェックするのではなく、特定の例外タイプをキャッチする必要があります。

于 2010-02-01T06:53:41.087 に答える
6

他の人はこれを潜在的な問題として指摘していますが、私は非常に明確な問題として提起したいと思います: あなたの using ステートメントは、現時点ではまったく役に立ちません。

次のような using ステートメントを記述すると、次のようになります。

SomeType x = value1;
using (x)
{
    x = value2;
}

ではなくvalue1、ブロックの最後に配置されるものです。あなたのコードでは、ブロック内まで null です。あなたが最終的に処分されることはありません。 value2responseWebResponse

次の行に沿って、これに関する警告が表示されるはずです。

警告 CS0728: using または lock ステートメントへの引数であるローカル 'response' への代入が正しくない可能性があります。Dispose 呼び出しまたはロック解除は、ローカルの元の値で発生します。

その警告は重要です - 注意してください。

それはさておき、try/catch ブロックを using ステートメントに配置することは完全に合理的ですが、この場合はおそらくusing ステートメントのresponseに置く必要があり、適切なタイミングで変数を初期化して、応答が常に処分した。また、「is」を繰り返し使用するのではなく、共通のメソッドを呼び出す複数の catch ブロックを使用することも検討します。

于 2010-02-01T07:13:03.350 に答える
1

これで全然OKです。例外を処理し、それ以上バブリングしたくない場合は、それで問題ありません。入れ子になった try/catch/finally ブロックは問題ありません。(内部的には、このような「使用」は単なる試行/最終です。)

更新:もう少し詳しく読んでください。実際には「try」ブロック内で使用する必要があると思います-実際にオブジェクトを「応答」変数に入れる行は、「使用」ブロックを開始したい場所です。実際にそのままコンパイルされますか?

于 2010-02-01T06:47:00.943 に答える