具有一次性成员的 C# ValueTuple

C# ValueTuple with disposable members

假设我有一个方法 foo,其中 returns 一个 ValueTuple 其中一个成员是一次性的,例如 (IDisposable, int).

确保调用方正确处理返回的一次性对象的最佳方法是什么?

我尝试了以下方法:

using (var (disposable, number) = foo())
{
    // do some stuff using disposable and number
}

但这不会编译:

'(IDisposable disposable, int number)': type used in a using statement must be implicitly convertible to 'System.IDisposable'

我真的需要将我的代码包装在一个 try-finally 块中并在 finally 块中显式处理我的对象,还是有更好的方法来做到这一点?

实际上我希望看​​到新的 ValueTuples 实现 IDisposable 接口并在其所有一次性成员上调用 Dispose()。这对 Microsoft 来说是一个有价值的功能请求吗?

只需将方法调用移到 using 语句之外,然后 使用 一次性 object:

var (disposable, number) = foo();
using (disposable)
{
    // do some stuff using disposable and number
}

您的版本不起作用的原因很简单,因为 using 括号内的表达式结果需要是一次性的,但值元组本身不是一次性的。所以你只需要把它分开。幸运的是,using 语句不需要 构造 该表达式中的 object,您可以将任何现有的 object 传递给它。


Actually I'd like to see the new ValueTuples implement the IDisposable interface and call Dispose() on all their disposable members. Could this be a worthwhile feature request for Microsoft?

按照这个逻辑,所有 collections 都必须这样做。例如,处理一个列表应该处理它的所有成员,处理一个字典应该处理它的所有值(和键?!?!)。当你有一个类型只使用一个简单的列表时,object 也需要是一次性的。

所以基本上,你最终会传播它并最终得到 很多 的 object,虽然它们实际上没有任何 实际 需要它的资源。

让 object 一次性使用绝非易事。通常,object 创建一次性 object 之后负责正确处理 object,他们 拥有 object 的生命周期.但是对于 collections,情况往往并非如此。 Collections 通常只是:Collections 持有 objects,但这并没有说明它们是否被 拥有 collection——大多数时候它们属于 object,也创建了 collection,因此 object 应该在某个时候处置 object s 通过简单地循环遍历 collection.