C# 从函数返回内存流

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/503789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 05:55:21  来源:igfitidea点击:

Returning memory stream from function

c#

提问by Amy

In your opinions, is it better to return a newly allocated memory stream from a function, or pass it into the function? For instance,

在您看来,是从函数返回新分配的内存流还是将其传递给函数更好?例如,

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

or

或者

void MemoryStream Foo()
{
    MemoryStream retval = new MemoryStream();
    retval.Write(somebuffer, 0, somebuffer.Length);
    return retval;
}

采纳答案by Jon Skeet

This is a bit like asking whether you should return a string from a method or take a StringBuilder and append to it. The answer depends on what the use case is.

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

Is it likely that the caller will want to call your method with an existing stream containing some data? Might they want to call it several times using the same stream? If so, the version taking the MemoryStream would be more efficient. On the other hand, if they only want the data once, returning it as a MemoryStream (or, more simply, as a byte array) may well be more appropriate.

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

Unfortunately from the description we can't really tell what's going on. Of course, you could implement both as overloads and call one from the other.

不幸的是,从描述中我们无法真正说出发生了什么。当然,您可以将两者都实现为重载并从另一个调用一个。

回答by Otávio Décio

You can safely return it from the function. You have to call Dispose()or put it inside a usingclause because it implements IDisposable.

您可以安全地从函数中返回它。您必须调用Dispose()或将其放入using子句中,因为它实现了 IDisposable。

回答by Andrew Hare

Your second one is better. I always try to avoid mutating objects inside functions if at all possible.

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

回答by Ray Booysen

There aren't two many differences. In the first instance the caller will have control over the memory stream and in the second instance, you can do something like this:

没有两个太多的区别。在第一个实例中,调用者将控制内存流,在第二个实例中,您可以执行以下操作:

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

The most important thing is to remember to dispose of it correctly.

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

回答by Pop Catalin

Passinga memory stream into a function and returninga memory stream for a function shouldn't be used interchangeably. The methods you describe serve two different purposes.

将内存流传递给函数并为函数返回内存流不应互换使用。您描述的方法有两个不同的目的。

  • Passing something to a function is for when you want the function to do something with the parameter.

  • Returning something from a function is when the caller is supposed to do something with the result.

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

  • 从函数返回一些东西是调用者应该对结果做一些事情的时候。

You are talking about two different things, apples and oranges.

你在谈论两种不同的东西,苹果和橙子。

回答by Marc Gravell

I would always pass the stream into the function. This allows it to work with any stream of the caller's choosing, for example straight into a file without any buffering.

我总是将流传递给函数。这允许它与调用者选择的任何流一起工作,例如直接进入文件而无需任何缓冲。

回答by tvanfosson

I would prefer the injected form. It removes the direct coupling between your code and the MemoryStream and it makes it more testable.

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

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

Now I can test Foo with any class that implements Stream including a mock class.

现在我可以使用任何实现 Stream 的类(包括模拟类)来测试 Foo。

Typically, I would do the injection in the constructor of the class rather than on individual methods but the idea is basically the same.

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

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 );
   }
}

回答by AwesomeTown

I would tend towards the first for two reasons:

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

  1. The semantics of who "owns" the memory stream are clear. The caller created it, so it's up to the caller to get rid of it (this is more of an issue with other types of streams that hold on to unmanaged resources)
  2. Foocan be used in conjunction with other methods that operate on your stream
  1. 谁“拥有”内存流的语义是明确的。调用者创建了它,因此由调用者来摆脱它(这对于保留非托管资源的其他类型的流来说更像是一个问题)
  2. Foo可以与对您的流进行操作的其他方法结合使用

That said, if the main purpose of Foois as a factory method for MemoryStreams (similar to something like File.Open, etc.), the second approach makes more sense.

也就是说,如果主要目的Foo是作为 MemoryStreams 的工厂方法(类似于 File.Open 等),则第二种方法更有意义。

回答by AwesomeTown

After some more thought, I think it comes down to the intended semantics of the Foomethod. Is it:

经过更多思考,我认为这归结为该Foo方法的预期语义。是吗:

  • An operation that creates a stream (eg. File.Open())
  • An operation that modifies a stream (eg. something.WriteXml())
  • 创建流的操作(例如。File.Open()
  • 修改流的操作(例如something.WriteXml()

If the answer is "creates a stream", have it return a stream. If it modifies a stream, pass the stream in.

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

If the answer is "some of both", it may make sense to split the method so that it has only a single responsibility.

如果答案是“两者兼而有之”,那么拆分方法使其只有一个职责可能是有意义的。

回答by Adrian Zanescu

Because streams are resources that need explicit disposal (memory, file, network) it is best to apply a RAII approach to handling them. That means that the function that initializes them must be responsible with the release (we have "using" keyord in C# just for that). To enable this pattern i say accepting the stream as a parameter. That way the caller can decide when to create and dispose the stream. While you're at it make your method accept any stream implementation; it does not seem like it needs to work only for MemoryStream.

因为流是需要显式处理的资源(内存、文件、网络),所以最好应用 RAII 方法来处理它们。这意味着初始化它们的函数必须负责发布(我们在 C# 中“使用”keyord 就是为此)。为了启用这种模式,我说接受流作为参数。这样调用者就可以决定何时创建和处理流。当你使用它时,让你的方法接受任何流实现;它似乎不需要仅适用于 MemoryStream。