避免在C#中使用`using`关键字进行多次处理的最佳做法

问题描述 投票:2回答:2

当变量是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 hangs after several requests (unless Fiddler is active)

c# windows-store-apps idisposable using-statement
2个回答
6
投票

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

在方法文档中指出调用者负责处理对象是个好主意。同样,一些方法接受一次性类型并声明调用者不应该自己处理对象。在这两种情况下,都有效地转移了妥善处理物品的责任。


0
投票

拥有返回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();
}

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

© www.soinside.com 2019 - 2024. All rights reserved.