13

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

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

我尝试了以下方法:

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

但这不会编译:

'(IDisposable 一次性,int number)':在 using 语句中使用的类型必须隐式转换为 'System.IDisposable'

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

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

4

1 回答 1

13

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

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

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


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

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

所以基本上,你最终会传播它并最终得到很多突然可以丢弃的对象,尽管它们实际上没有任何需要它的实际资源。

制作一次性物品不应该轻易完成。通常,创建一次性对象的对象稍后会负责正确处理对象,它们拥有对象的生命周期。但对于收藏,情况往往并非如此。集合通常就是这样: 持有对象的集合,但这并没有说明它们是否由集合拥有——大多数情况下,它们由也创建集合的对象拥有,因此该对象应该然后在某个时候通过简单地遍历集合来处理对象。

于 2017-09-26T12:23:48.183 回答