C# try/catch应该在using块的内部还是外部?

C# try/catch应该在using块的内部还是外部?,c#,exception-handling,C#,Exception Handling,我相信,using块是try/catch/finally的缩写。在我的代码中,我一直在using块中放置一个try/catch块,这样我就可以使用自己的记录器捕获并记录异常 我最近一直想知道try是否应该在外部,从而使用块封装 在我看来,我之前一直担心,如果抛出异常,那么using块将不会Dispose(),因为它已跳出块并进入catch处理程序。但我可能错了 有人能澄清一下,同时使用和try/catch的正确方法是什么吗 public HttpResponseMessage GetData(s

我相信,
using
块是
try/catch/finally
的缩写。在我的代码中,我一直在
using
块中放置一个
try/catch
块,这样我就可以使用自己的记录器捕获并记录异常

我最近一直想知道
try
是否应该在外部,从而使用
块封装

在我看来,我之前一直担心,如果抛出异常,那么
using
块将不会
Dispose()
,因为它已跳出块并进入catch处理程序。但我可能错了

有人能澄清一下,同时使用
try/catch
的正确方法是什么吗

public HttpResponseMessage GetData(string x, int y)
{
    using (var client = new HttpClient())
    {
        try
        {
            // do stuff

            return response.Result;
        }
        catch (Exception ex)
        {
            // Something has gone badly wrong so we'll need to throw

            // Log the info

            throw;
        }
    }
}

using
块用于确保在
using
语句中声明的对象在代码脱离
using
块后立即进行处置(从模糊的“立即处置”术语改为建议的处置)。它并不是try/catch/finally的缩写。(但请注意)

在你的例子中

using (var client = new HttpClient())
{
} //client will be disposed at any time after this line

取决于情况,您可以考虑使用< <代码>块> >代码> > catch > <代码>块。

例如,如果您不需要多次使用
using
声明中的项(编辑:我的意思是如果您在
try
catch
块中都需要该项,谢谢您的输入)-也就是说,您只需要在
try
中使用它,我建议在
try
块中使用
use

转换为您的情况,这取决于
var-client
是否同时用于
try
catch
块。如果是,则使用的
应在
try catch
块之外。否则,它应该在
try
块中


一般来说,根据经验,如果在
try
catch
块中同时使用该项,则在
try catch

之外仅使用
一次声明
。使用块保证总是在退出时调用
Dispose()
方法-即使是在堆栈中捕获的异常的堆栈解缠也是如此

using语句确保即使在调用对象上的方法时发生异常,也会调用Dispose。通过将对象放在try块中,然后在finally块中调用Dispose,可以获得相同的结果;事实上,编译器就是这样翻译using语句的。前面的代码示例在编译时扩展为以下代码(注意额外的大括号用于创建对象的有限范围):


没有“正确的方法”,只有指导方针。但是我自己尽可能地本地化每个异常或任何代码,这意味着您应该在可以抛出异常的地方创建一个异常,但是在外部的某个地方,至少只要您不必让异常冒泡通过不同的层。

这实际上取决于您担心被处置的资源是什么-如果您指的是
客户机
,您应该没事。我会解释为什么

在我看来,我之前一直担心,如果抛出异常,那么using块将不会Dispose()处理我的资源,因为它已跳出块并跳入catch处理程序。但我可能错了

这不是它的工作方式,编译器可能会重写您的代码(可能效率更高),如下所示:

在正常情况下,
finally
块将始终执行,这意味着,即使您使用
捕获/重试
中的异常,也会触发您的
Dispose
调用


因此,从技术角度来看,内部与外部实际上并不重要。

就我个人而言,我会使用
块将try/catch/finally放在
中。

原因很简单,就是
using
块本身不会抛出异常,至少根据我的经验不会。因此,为了简单起见,我将处理发生异常的地方

如果有
using
块,则不必使用try/catch。尤其不需要捕获异常并立即重新显示它。如果您只想记录异常,请订阅
AppDomain.UnhandledException
事件。在这种情况下,我还会将其放入using块中。但是,正如其他人所说,没有正确的方法可以做到这一点。使用
块并不是try/catch/finally的简写。一个
using
块用于在不再需要某个对象时自动处理该对象。如果您要抛出该对象,它是否会自动处理;里面?去一趟怎么样?我会对“立即处置”一词保持警惕,我明白你的意思,即
Dispose
将被调用,但这肯定不能保证垃圾收集方面的立即处置。你说的“重新声明”到底是什么意思?在using语句中只声明了一次。@James啊,是的,因为没有更好的术语。。。还有更好的建议吗?我对此持开放态度。要不然,我就贴张便条?@CodyGray我的意思是,如果你在试球和接球区都需要它的话。。。然后它需要重新声明…@Ian我真的要去掉“立即”这个词
try
{
    try
    {
        // do stuff
        return response.Result;
    }
    catch (Exception ex)
    {
        // Something has gone badly wrong so we'll need to throw
        // Log the info
        throw;
    }
}
finally
{
    if (client != null)
        client.Dispose();
}