在函数中关闭一个流,一个坏主意?

时间:2012-04-05 20:17:19

标签: c# exception-handling io

我今天写了一些代码,另一位开发人员改变了它,说它更安全。我不确定这是对的,因为我看不出这里所做的是一些代码示例的优势

public byte[] ReadFile(Stream stream)
{
    byte[] result = null;

    try
    {
       // do something with stream
       result = <result of operation>
    }
    finally
    {
        stream.Close();
    }

    return result;
}

这已改为

public byte[] ReadFile(Stream stream)
{
    byte[] result = null;

    // do something with stream
    result = <result of operation>

    return result;
}

如果你完成它后流不被关闭,我对c#很新吗?

7 个答案:

答案 0 :(得分:11)

一般来说,第一个版本的设计不好。

是的,应关闭Stream,但最好使用打开它的相同代码(相同方法)。这被称为关注点的分离,它使错误和混淆的可能性大大降低。

所以要么

  • 您的ReadFile()接受例如string fileName并打开并关闭流,或
  • 你把它留给来电者。

您的方法(第2版)应该以这种方式使用:

using (var reader = new FileReader(...))
{
  // maybe some pre-reading
  var r = ReadFile(reader);
  // maybe some post-reading
}

请注意,第二种方法也使该方法更具可重用性。

答案 1 :(得分:6)

这个问题没有正确答案,因为这取决于您的应用程序架构。

我会说,是的,因为如果在这个函数stream中没有创建,只有使用,所以关闭它让我们放手呼叫者。

但我再说一遍,这取决于您的应用架构。

答案 2 :(得分:5)

谁打开门必须记得关闭它。

因此最好在打开它的方法中关闭流。

答案 3 :(得分:3)

通常,Stream的创建者应该是关闭它的创建者,理想情况是通过使用using块来处理它:

using (var myStream = getMeAStream()) {
    ReadFile(myStream);

    // If you want to be really sure it is closed:
    myStream.Close();
    // Probably not neccessary though, since all 
    // implementations of Stream should Close upon Disposal
}

答案 4 :(得分:1)

流已经通过其他东西传递给了这个函数,你不负责关闭它的函数,它取决于调用代码来处理这个问题。

原因是可能需要在此函数外部执行另一个操作(如重置或其他读取),如果关闭它,则会导致异常。

我曾经每天多次重构这样的代码,直到最后有人听我说。

我已经看到至少有一个由这种代码引起的严重错误,所以一般来说这是一个坏主意

答案 5 :(得分:0)

代码审查是对的 - 从来没有做过这样的事情(或者如果外部代码需要这样的东西那么代码可能没有正确设计 - 有例外但是像流处理这样的东西几乎从来没有,和总是要遵循一些默认的“模式” 在大多数情况下使用这样的流(来自“外部”)......

using(Stream stream = new ...)
{
    ...call your method
}

(或者例如读者正在处理它 - 但是建议你在任何一种情况下都做这样的事情 - 相当于使用'finally'块,但归结为同样的事情)

...基本上调用函数永远不会知道你是否在“内部”处理它 - 直到它崩溃了。如果“两个部分”都同意这样的话,那么它仍然是不可接受的,但可能会逍遥法外。

答案 6 :(得分:0)

这不仅仅是一个C#问题。在调用函数“ReadFile”之后,您需要将该流用于其他操作吗?如果没有,您可以在阅读文件后选择关闭流。 当你完成使用它们时,最好关闭流,但通常我更喜欢在相同的上下文中关闭它们而不是打开它们,因为它就是你知道是否需要流进行其他操作的地方:

Stream s = open_the_stream()
try {
  ReadFile(s)...
} finally {
  s.Close();
}

以任何方式,当您终止使用它们时关闭流。