6

可以在 Web 请求的“使用”语句中嵌入“尝试/捕获”吗?我的代码正确吗?那就是我的要求是:

  1. 想要使用“using”语句来确保在任何情况下都为 HttpWebResponse 释放资源

    • 但是如果有异常 re 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块,在 之后添加一个finallycatch,并在那里显式调用Dispose,这将减少代码中的嵌套。

在更具体的意义上,让我感到有点困扰的是,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被放置在块的末尾,而不是 value2. 在您的代码中,response在块内之前为 null;WebResponse你最终得到的将不会处理。

您应该会看到关于此的警告,大致如下:

警告 CS0728:可能不正确地分配给本地“响应”,这是使用或锁定语句的参数。Dispose 调用或解锁将发生在本地的原始值上。

这个警告很重要——注意它。

撇开这一点不谈,将 try/catch 块放在 using 语句中是完全合理的……但在这种情况下,它可能应该在 using 语句之外,让您response在适当的时间初始化变量,以便响应始终是处置。我也会考虑使用多个 catch 块调用一个通用方法,而不是重复使用“is”。

于 2010-02-01T07:13:03.350 回答
1

这完全没问题。您处理异常并且不希望它进一步冒泡,这很好,嵌套的 try/catch/finally 块没有问题。(在内部,像这样的“使用”只是一次尝试/最终。)

更新:仔细阅读,我认为您实际上希望在“尝试”块内使用 - 您实际将对象放入“响应”变量的行是您希望“使用”块开始的位置。它真的按原样编译吗?

于 2010-02-01T06:47:00.943 回答