在您看来,最好从函数返回一个新分配的内存流,还是将其传递给函数?例如,
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;
}
答案 0 :(得分:17)
这有点像询问是否应该从方法返回一个字符串或者接受一个StringBuilder并附加到它。答案取决于用例是什么。
调用者是否可能希望使用包含某些数据的现有流来调用您的方法?他们可能想使用相同的流多次调用它?如果是这样,采用MemoryStream的版本将更有效。另一方面,如果他们只想要一次数据,那么将它作为MemoryStream(或者更简单地,作为字节数组)返回可能更合适。
不幸的是,从描述中我们无法确切地知道发生了什么。当然,你可以将它们实现为重载并从另一个中调用一个。
答案 1 :(得分:7)
将内存流传递给函数,返回函数的内存流不应互换使用。您描述的方法有两个不同的用途。
将函数传递给函数是为了让函数对函数执行某些操作。
从函数中返回一些内容是调用者应该对结果做某事。
你说的是两个不同的东西,苹果和橘子。
答案 2 :(得分:4)
我总是将流传递给函数。这允许它与调用者选择的任何流一起工作,例如直接进入文件而不进行任何缓冲。
答案 3 :(得分:2)
您可以安全地从功能中返回它。您必须调用Dispose()
或将其放在using
子句中,因为它实现了IDisposable。
答案 4 :(得分:1)
你的第二个更好。如果可能的话,我总是尽量避免在函数内部变异。
答案 5 :(得分:1)
经过一番思考之后,我认为它归结为Foo
方法的预期语义。是吗:
File.Open()
)something.WriteXml()
)如果答案是“创建流”,请让它返回一个流。如果它修改了一个流,则将该流传递给。
如果答案是“两者中的某些”,那么拆分方法以使其只有一个责任可能是有意义的。
答案 6 :(得分:0)
没有两个差异。在第一个实例中,调用者将控制内存流,在第二个实例中,您可以执行以下操作:
using (MemoryStream ms = Foo())
{
//Do Stuff here.
}
最重要的是要记住正确处理它。
答案 7 :(得分:0)
我更喜欢注射形式。它消除了代码与MemoryStream之间的直接耦合,使其更易于测试。
public void Foo(Stream stream)
{
stream.Write(somebuffer, 0, somebuffer.Length);
}
现在,我可以使用任何实现Stream的类来测试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 );
}
}
答案 8 :(得分:0)
我倾向于第一个,原因有两个:
Foo
可以与您在流上运行的其他方法结合使用也就是说,如果Foo
的主要目的是作为MemoryStreams的工厂方法(类似于File.Open等),第二种方法更有意义。
答案 9 :(得分:0)
因为流是需要显式处理的资源(内存,文件,网络),所以最好应用RAII方法来处理它们。这意味着初始化它们的函数必须对发布负责(我们在C#中使用“使用”keyord)。为了启用这种模式,我说接受流作为参数。这样,调用者可以决定何时创建和处理流。当你在它时,你的方法接受任何流实现;它似乎不仅仅适用于MemoryStream。