简体   繁体   English

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

[英]c# - is it ok to embed a “try/catch” within a “using” statement for a web request? Is my code correct?

Is it ok to embed a "try/catch" within a "using" statement for a web request? 是否可以在“using”语句中为Web请求嵌入“try / catch”? Is my code correct? 我的代码是否正确? That is my requirements are: 那是我的要求是:

  1. Want to use the "using" statement to make sure resources are released in any case for HttpWebResponse 想要使用“using”语句来确保在任何情况下都为HttpWebResponse释放资源

    • But still want to do some custom stuff if there is an exception re HttpWebResponse and "response = (HttpWebResponse)request.GetResponse();" 但是如果有一个例外的HttpWebResponse和“response =(HttpWebResponse)request.GetResponse();”仍然想做一些自定义的东西。 in particular. 尤其是。

My source code: 我的源代码:

        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; }
            }

        }

thanks 谢谢

It is OK, but a little redundant; 没关系,但有点多余; in a general sense, you could easily remove the using block, add a finally block after the catch , and explicitly call Dispose in there, which would reduce the nesting in your code. 在一般意义上,您可以轻松地删除using块,在catch之后添加finally块,并在那里显式调用Dispose ,这将减少代码中的嵌套。

In a more specific sense, what bugs me a little is that you don't actually assign response until you get inside the using block, and the explicit variable declarations are unnecessary and confusing in this context. 在更具体的意义上,让我感到困惑的是, 进入using块之前,实际上并没有分配response ,并且显式变量声明在此上下文中是不必要的并且令人困惑。 I would rewrite it as: 我会把它重写为:

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.
}

This is a lot clearer than the original form. 这比原始形式更清晰。 Also note that I'm catching WebException , not the generic System.Exception . 另请注意,我正在捕获WebException ,而不是通用的System.Exception You should catch specific exception types instead of catching generic exceptions and then checking their type. 您应该捕获特定的异常类型,而不是捕获一般异常,然后检查它们的类型。

Others have pointed this out as a potential problem, but I want to raise it as a very definite problem: your using statement is doing you no good at all at the moment. 其他人已经指出这是一个潜在的问题,但我想把它作为一个非常明确的问题提出来:你的使用陈述目前对你没有任何好处。

When you write a using statement like this: 当你编写这样的using语句时:

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

it is value1 which will be disposed at the end of the block, not value2 . 它是value1 ,它将被置于块的末尾, 而不是 value2 In your code, response is null until inside the block; 在您的代码中, response在块内部为空; the WebResponse you end up with will not be disposed. 您最终得到的WebResponse不会被处置。

You should be seeing a warning about this, along these lines: 您应该看到关于此的警告,沿着这些方向:

warning CS0728: Possibly incorrect assignment to local 'response' which is the argument to a using or lock statement. 警告CS0728:可能不正确地分配给本地“响应”,这是使用或锁定语句的参数。 The Dispose call or unlocking will happen on the original value of the local. Dispose调用或解锁将发生在本地的原始值上。

That warning is important - heed it. 这个警告很重要 - 注意它。

Leaving that aside, it's entirely reasonable to put a try/catch block in a using statement... but in this case it should probably be outside the using statement, letting you initialize the response variable at the appropriate time so that the response will always be disposed. 抛开这一点,将try / catch块放在using语句中是完全合理的......但在这种情况下,它应该在using语句之外 ,让你在适当的时候初始化response变量,这样响应总会被处置。 I would also consider using multiple catch blocks calling a common method rather than using "is" repeatedly. 我还会考虑使用多个catch块来调用常用方法,而不是反复使用“is”。

This is totally OK. 这完全没问题。 You handle the exception and don't want it bubbling up further, that's just fine, and nested try/catch/finally blocks are no problem. 你处理异常并且不希望它进一步冒泡,这很好,并且嵌套的try / catch / finally块没有问题。 (Internally a 'using' like this is just a try/finally.) (在内部,像这样'使用'只是一个尝试/最终。)

UPDATE: read a little closer, and I think you actually want the using inside the 'try' block - the line where you actually put an object in the 'response' variable is where you want the 'using' block to begin. 更新:仔细阅读,我认为你实际上想要在'try'块中使用 - 你在'response'变量中实际放置一个对象的行是你想要'using'块开始的地方。 Does it actually compile as-is? 它实际上是按原样编译的吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM