7

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

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# 很陌生,当你完成后不应该关闭流吗?

4

7 回答 7

11

一般来说,第一个版本是一个糟糕的设计。

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

所以要么

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

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

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

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

于 2012-04-05T20:19:55.673 回答
6

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

我会说,是的,因为如果在这个函数stream中没有创建,而只是使用了,所以关闭它让我们交给调用者。

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

于 2012-04-05T20:20:14.557 回答
5

开门的人一定要记得关门。

所以最好在打开它的方法中关闭流。

于 2012-04-05T20:20:32.080 回答
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
}
于 2012-04-05T20:21:33.693 回答
1

流已经被其他东西传递到这个函数中,你不负责关闭它,由调用代码来处理这个问题。

原因是另一个操作(如重置或另一个读取)可能需要在这个函数的外部完成,如果你关闭它,你会导致异常。

我曾经每天多次重构这样的代码,直到终于有人听了我的意见。

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

于 2012-04-05T20:22:38.647 回答
0

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

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

无论如何,当您终止使用它们时关闭流。

于 2012-04-05T20:25:47.370 回答
0

代码审查是正确的——永远不要做这样的事情(或者如果外部代码需要这样的事情,那么该代码可能没有正确设计——有例外,但对于像流这样的事情几乎从来没有,而且一些默认的'模式”总是要遵循的)。
在大多数情况下,使用这样的流(来自“外部”)......

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

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

...基本上,调用函数永远不会知道您是否将其处理“内部” - 直到它崩溃。如果“双方”就这样的事情达成一致,那么这仍然是不可接受的,但可能不受惩罚。

于 2012-04-05T20:21:27.413 回答