假设我有一个方法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()
。这可能是微软的一个有价值的功能请求吗?
答案 0 :(得分:9)
只需将方法调用移到using
语句之外,然后只需使用一次性对象:
var (disposable, number) = foo();
using (disposable)
{
// do some stuff using disposable and number
}
你的版本不起作用的原因仅仅是因为using
括号内的表达式需要是一次性的,但值元组本身不是一次性的。所以你只需要拆分它。幸运的是,构造该表达式中的对象不需要using
语句,您只需将任何现有对象传递给它。
实际上,我希望看到新的ValueTuples实现
IDisposable
接口,并在所有可丢弃成员上调用Dispose()
。这可能是微软的一个有价值的功能请求吗?
按照这种逻辑,所有集合都必须这样做。例如,处理一个列表应该处理它的所有成员,处理一个字典应该处理它的所有值(和键?!?!)。当你有一个只使用简单列表的类型时,该对象也需要是一次性的。
所以基本上,你最终会传播它并最终使用很多突然丢弃的对象,尽管它们实际上并没有任何需要的实际资源它
制作一次性物品不应轻易做到。通常,创建一次性对象的对象负责在以后正确处理对象,它们拥有对象的生命周期。但对于收藏品而言,情况往往并非如此。集合通常只是:用于保留对象的集合,但是没有说明它们是否由集合拥有 - 大多数时候它们也由创建的对象拥有集合,因此对象应该在某个时候通过简单地循环遍历集合来处理对象。