【问题标题】:`using()` on a stream returned from a method [duplicate]在从方法返回的流上使用()
【发布时间】:2018-11-28 09:19:45
【问题描述】:

假设我有一个带有 ToStream() 方法的字符串类。

class FooBar
{
    pubic Stream ToStream( )
    {
        byte[ ] barFooBytes = Encoding.UTF8.GetBytes( this.BarFoo );
        return new MemoryStream( barFooBytes );
    }
}

现在假设我有一个类得到这个流。

class BarFoo
{
    pubic void DoCrazyStuff( )
    {
        using( Stream fooBarStream = ( new FooBar( ) ).ToStream( ) )
        {
            // Doing some really crazy stuff!
        }
    }
}

在创建流的方法之外使用using 仍然有意义吗?

提示: 这不是真实的现实生活场景。这是一个纯粹的技术问题。所以这个代码被缩小只是为了澄清问题。

【问题讨论】:

  • 为什么new Foobar() - 如果ToStream 方法不需要持久实例状态,为什么不将其设为静态方法?
  • 假设我可以创建一个Action<List<MyAwesomeClass>>,这有意义吗?唯一正确的答案是:视情况而定。我们需要了解更多细节才能做出有根据的猜测。
  • 另外,如果数据本身是Byte[],我建议不要将Byte[] 作为MemoryStream 返回,除非您在其他地方有需要它的约束或用例。如果数据主要是Byte[],但某些消费者需要它作为Stream,那么将其包装在MemoryStream 中应该是消费者的责任,而不是生产者的责任。
  • 请不要用脏话提问,谢谢
  • @dai 问题不在于FooBar 的实例化。这是关于流上的using 作为返回值。而这个 sn-p 只是说明了我的意思。 @liam 我在哪里使用了脏话?

标签: c# using


【解决方案1】:

对于using/IDisposable,可以随时回答的重要问题是“谁拥有这个对象?”。在这种情况下,ToStream 方法必须返回一个Stream,因此虽然它在运行时拥有该对象,但它和它所属的类不再承担任何责任。因此它不会 Dispose 或将其包装在 using 中。

因此,我们可以确定对象的所有权已经传回给ToStream 方法的调用者。因此,作为对象的新所有者,您有责任将其包装在 using、手动 Dispose 或将所有权传递给其他对象。


正如John's answer 和它下面的cmets 所指出的,MemoryStream 并没有显着受益于Dispose 被调用(缓冲区保持分配状态)。但是,它实现了Dispose,因为它继承自Stream,并且在合同上,您的ToStream 方法承诺提供的只是Stream,而不是MemoryStream,因此using/Dispose 是正确的调用者。

【讨论】:

  • 我希望 C# 9.0 增加像 Rust 的所有权和借用语义这样的东西,因为这完全解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 2019-07-13
  • 2020-06-10
  • 2021-10-17
  • 2015-05-02
相关资源
最近更新 更多