【问题标题】:C# ValueTuple with disposable members具有一次性成员的 C# ValueTuple
【发布时间】:2017-09-26 12:21:13
【问题描述】:

假设我有一个方法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()。这对微软来说是一个有价值的功能请求吗?

【问题讨论】:

  • 何时会在此 IDisposable ValueTuple 上调用 Dispose?甚至垃圾收集器也不会调用 Dispose。如果您希望垃圾收集器触发它,您必须编写该代码并至少将其放入终结器中。
  • 如果你应该实现 IDisposable 那么就不要使用元组。

标签: c# using idisposable valuetuple


【解决方案1】:

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

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

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


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

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

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

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

【讨论】:

  • 我正要接受这个答案......但这里有一个问题:如果foo() 在创建一次性对象后抛出异常怎么办?看起来为了安全起见,我仍然需要将所有内容都包装在 try-finally 块中??
  • 由于foo在抛出异常时无法返回任何内容,因此清理函数内部状态不是调用代码的责任。所以是的,如果函数在创建对象后可能抛出异常,它应该正确处理这种情况并在异常冒泡之前处理对象。
猜你喜欢
  • 1970-01-01
  • 2018-06-13
  • 2018-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多