代码之家  ›  专栏  ›  技术社区  ›  Amy

从函数返回内存流

c#
  •  22
  • Amy  · 技术社区  · 16 年前

    在您看来,从一个函数返回一个新分配的内存流,或者将它传递给该函数,是更好的选择?例如,

    void Foo(MemoryStream m) 
    { 
       m.Write(somebuffer, 0, somebuffer.Length); 
    }
    

    void MemoryStream Foo()
    {
        MemoryStream retval = new MemoryStream();
        retval.Write(somebuffer, 0, somebuffer.Length);
        return retval;
    }
    
    10 回复  |  直到 11 年前
        1
  •  17
  •   Jon Skeet    16 年前

    这有点像询问您是应该从一个方法返回一个字符串,还是接受一个StringBuilder并附加到它上面。答案取决于用例是什么。

    调用方是否希望使用包含某些数据的现有流调用方法?他们想用同一个流多次调用它吗?如果是这样,那么使用memoryStream的版本将更加高效。另一方面,如果他们只需要数据一次,将其作为内存流(或者更简单地说,作为字节数组)返回可能更合适。

    不幸的是,从描述上看,我们无法真正判断到底发生了什么。当然,您可以实现两个重载,并从另一个重载中调用一个重载。

        2
  •  7
  •   Pop Catalin    16 年前

    经过 将内存流转换为函数并 返回 函数的内存流不能互换使用。您描述的方法有两个不同的用途。

    • 当您希望函数对参数执行某些操作时,将某些内容传递给函数。

    • 从函数返回某些内容是指调用者应该对结果做些什么。

    你说的是两种不同的东西,苹果和桔子。

        3
  •  3
  •   Marc Gravell    16 年前

    我总是将流传递到函数中。这允许它处理调用者选择的任何流,例如直接进入文件而不进行任何缓冲。

        4
  •  2
  •   Otávio Décio    16 年前

    您可以从函数中安全地返回它。你得打电话 Dispose() 或者把它放进 using 子句,因为它实现了IDisposable。

        5
  •  1
  •   Andrew Hare    16 年前

    你的第二个更好。如果可能的话,我总是尽量避免在函数内部改变对象。

        6
  •  1
  •   Rui Jarimba    11 年前

    经过更多的思考,我认为它归结为 Foo 方法。它是:

    • 创建流的操作(例如 File.Open() )
    • 修改流的操作(如 something.WriteXml() )

    如果答案是“创建流”,请让它返回流。如果修改了流,则传入该流。

    如果答案是“两者兼而有之”,那么分割方法可能是有意义的,这样它就只有一个责任。

        7
  •  0
  •   Ray Booysen    16 年前

    没有什么区别。在第一个实例中,调用者将控制内存流,在第二个实例中,您可以这样做:

    using (MemoryStream ms = Foo())
    {
      //Do Stuff here.
    }
    

    最重要的是要记住正确处理它。

        8
  •  0
  •   tvanfosson    16 年前

    我更喜欢注射式的。它消除了代码和MemoryStream之间的直接耦合,使其更具可测试性。

    public void Foo(Stream stream)
    {
        stream.Write(somebuffer, 0, somebuffer.Length);
    }
    

    现在,我可以用任何实现流的类(包括模拟类)测试foo。

    通常,我会在类的构造函数中进行注入,而不是在单个方法上进行注入,但其思想基本上是相同的。

    public class FooClass
    {
       public Stream FooStream { get; private set; }
    
       public FooClass() : this(null) { }
    
       public FooClass( Stream stream )
       {
           // provide a default if not specified
           this.FooStream = stream ?? new MemoryStream();
       }
    
       public void Foo()
       {
           this.FooStream.Write( somebuffer, 0, somebuffer.Length );
       }
    }
    
        9
  •  0
  •   AwesomeTown    16 年前

    我倾向于第一个原因有两个:

    1. 谁“拥有”内存流的语义是清晰的。调用者创建了它,因此由调用者来消除它(这更像是其他类型的流持有非托管资源的问题)
    2. Foo 可以与对流进行操作的其他方法一起使用

    也就是说,如果主要目的是 作为内存流的工厂方法(类似于file.open等),第二种方法更有意义。

        10
  •  0
  •   Adrian Zanescu    16 年前

    因为流是需要显式处理(内存、文件、网络)的资源,所以最好使用raii方法来处理它们。这意味着初始化它们的函数必须与发布负责(我们在C中有“使用”keyord)。要启用这个模式,我说接受流作为参数。这样,调用方就可以决定何时创建和释放流。当您处理它时,使您的方法接受任何流实现;它似乎不需要只对memorystream有效。