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) 只保留using在一起new,其他情况下不需要?:

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 处于活动状态)

4

2 回答 2

6

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

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

于 2013-05-31T15:59:12.787 回答
0

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

否则,如果您希望您的方法的返回值是一个 new 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();
}

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

于 2013-05-31T17:44:46.973 回答