代码之家  ›  专栏  ›  技术社区  ›  Greg

C-是否可以在Web请求的“using”语句中嵌入“try/catch”?我的代码正确吗?

  •  6
  • Greg  · 技术社区  · 15 年前

    是否可以在Web请求的“using”语句中嵌入“try/catch”?我的代码正确吗?这是我的要求:

    1. 希望使用“using”语句确保在任何情况下都为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; }
                }
    
            }
    

    谢谢

    3 回复  |  直到 15 年前
        1
  •  9
  •   Aaronaught    15 年前

    可以,但有点多余;从一般意义上讲,您可以轻松地删除 using 块,添加 finally 后面的块 catch ,并显式调用 Dispose 这样可以减少代码中的嵌套。

    在更具体的意义上,让我有点恼火的是你实际上没有分配 response 直到你得到 里面 这个 使用 块和显式变量声明在这个上下文中是不必要的和混乱的。我会把它改写为:

    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 . 您应该捕获特定的异常类型,而不是捕获一般异常,然后检查它们的类型。

        2
  •  6
  •   Jon Skeet    15 年前

    其他人指出这是 潜在的 问题,但我想把它作为 非常明确 问题:你的使用声明目前对你一点好处也没有。

    当您编写这样的using语句时:

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

    它是 value1 将在块的末端处理, value2 . 在您的代码中, response 在块内之前为空;该 WebResponse 你最终会得到威尔 被处置。

    您应该看到一条关于这一点的警告,沿着这条线:

    警告CS0728: 可能不正确地分配给本地 “响应”,其中 是using或lock语句的参数。释放调用或 解锁将发生在本地的原始值上。

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

    撇开这一点不谈,在using语句中放置try/catch块是完全合理的…但在这种情况下,应该是 外部 using语句,允许您初始化 响应 变量,以便始终释放响应。我还考虑使用多个catch块调用一个公共方法,而不是重复使用“is”。

        3
  •  1
  •   Bruce    15 年前

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

    更新:仔细阅读,我认为你实际上想要在“try”块中使用-你在“response”变量中实际放置对象的那一行就是你想要“using”块开始的地方。它实际上是按原样编译的吗?