避免在C#中使用关键字“using”进行多次处置的最佳实践

本文关键字:最佳 using 关键字 | 更新日期: 2023-09-27 18:16:22

当变量是IDisposable时,我们有using关键字来管理处理。但是,如果我们在一个方法中返回值,我们应该有两次using吗?

StringContent stringToStringContent(string str)
{
    using (StringContent content = new StringContent(str))
    {
        return content;
    }
}
void logStringContent()
{
    using (StringContent content = stringToStringContent("test"))
    {
        Debug.WriteLine(content.ToString());
        return;
    }
}

在上面的这个例子中,我只有1个new,但对于相同的东西,我有2个using。所以我觉得它不平衡。更好的做法是:

a( 同时保留using,并且语言/编译器知道它的工作以避免双重处理?

b( 只保留usingnew在一起,其他情况下不需要?:

void logStringContent()
{
    StringContent content = stringToStringContent("test");
    Debug.WriteLine(content.ToString());
    return;
}

c( 不回来时只保留using,回来时不需要?:

StringContent stringToStringContent(string str)
{
    return new StringContent(str);
}

我唯一能感觉到的是,b(不是正确的答案,因为它不适用于这里描述的问题:。NET HttpClient在多次请求后挂起(除非Fiddler处于活动状态(

避免在C#中使用关键字“using”进行多次处置的最佳实践

我认为c在这里是正确的答案-您正在从方法中返回一个对象(对它的引用(-在返回该对象之前已经处理掉它是没有意义的。例如,File.OpenRead不会处理它返回的流,是吗?

不过,最好在方法文档中指出调用者负责处理对象。同样,一些方法接受一个可丢弃类型,并声明调用者不应该自己处理对象。在这两种情况下,都有效地转移了正确处理物体的责任。

拥有返回IDisposable对象的方法并不是一种常见的模式,但在发生异常时防止资源泄漏可能很困难。另一种方法是让一个产生新的IDisposable的方法接受out或(如果该方法是未密封的和虚拟的(ref参数,并在其中存储对新对象的引用。然后,调用者将被期望Dispose有问题的东西,无论产生它的方法是正常返回还是抛出异常。

否则,如果你希望你的方法的返回值是一个新的IDisposable,并且在你的方法获取资源和返回之间有任何代码要执行,你应该用类似的东西来保护你的代码:

DisposableThing thingToDispose = null;
try
{
    thingToDispose = new DisposableThing(whatever);
    // Now do stuff that might throw.
    // Once you know you're going to return successfully...
    DisposableThing thingToReturn = thingToDispose;
    thingToDispose = null;
    return thingToReturn;
}
finally
{
    if (thingToDispose != null)
      thingToDispose.Dispose();
}

请注意,此代码不会"捕获"任何异常,但如果函数不是通过正确的指定路径退出,则新构建的对象将被丢弃。请注意,如果此函数在不处理新构建的对象的情况下抛出异常,则该对象获取的任何资源都将泄漏,因为调用者将无法处理它。