带有一次性成员的C#ValueTuple

时间:2017-09-26 12:21:14

标签: c# using idisposable valuetuple

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

确保返回的一次性物体在呼叫方面正确处理的最佳方法是什么?

我尝试了以下内容:

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

但这不会编译:

  

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

我是否真的需要将我的代码包装在try-finally块中并将我的对象显式地放在finally块中,还是有更好的方法呢?

实际上,我希望看到新的ValueTuples实现IDisposable接口并在所有可丢弃成员上调用Dispose()。这可能是微软的一个有价值的功能请求吗?

1 个答案:

答案 0 :(得分:9)

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

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

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

  

实际上,我希望看到新的ValueTuples实现IDisposable接口,并在所有可丢弃成员上调用Dispose()。这可能是微软的一个有价值的功能请求吗?

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

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

制作一次性物品不应轻易做到。通常,创建一次性对象的对象负责在以后正确处理对象,它们拥有对象的生命周期。但对于收藏品而言,情况往往并非如此。集合通常只是:用于保留对象的集合,但是没有说明它们是否由集合拥有 - 大多数时候它们也由创建的对象拥有集合,因此对象应该在某个时候通过简单地循环遍历集合来处理对象。