为什么Code Analysis会告诉我,"不要多次丢弃对象"这里:

时间:2014-06-20 23:14:52

标签: c# visual-studio-2013 filestream dispose binaryreader

关于此代码:

public static string Base64FromFileName(string fileName)
{
    try
    {
        FileInfo fInfo = new FileInfo(fileName);
        long numBytes = fInfo.Length;
        FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
        BinaryReader br = new BinaryReader(fStream);
        byte[] bdata = br.ReadBytes((int)numBytes);
        br.Close();
        fStream.Close();
        return Convert.ToBase64String(bdata);
    }
    catch(Exception e)
    {
        throw e;
    }
}

...我得到了,Visual Studio的代码分析工具,警告," 不要多次丢弃对象...为了避免生成System.ObjectDisposedException,你不应该调用在对象上多次处理"在" fStream.Close();"线。

为什么呢? fStream是否在上面的行中,BinaryReader被关闭了?

无论如何我最好不要像这样重构它:

. . .
using (FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))   
{
    using (BinaryReader br = new BinaryReader(fStream)) 
    {
        byte[] bdata = br.ReadBytes((int)numBytes);
    } //br.Close();
} //fStream.Close();
. . .

2 个答案:

答案 0 :(得分:5)

BinaryReader.Close也会关闭基础流,因此这确实会导致流被处理两次。但这不是一个真正的问题,处理两次并不会造成伤害。

你可以写得更好

using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
using (var br = new BinaryReader(fs, new UTF8Encoding(), true))
{
    return Convert.ToBase64String(br.ReadBytes((int)numBytes));
}

这是防弹版:

  • 保证成功构建的任何内容
  • 您不会两次处理该流,因为leaveOpen构造函数上的布尔BinaryReader参数确保处置(关闭)它也不会关闭流

答案 1 :(得分:3)

代码分析是对的;代码分析是错误的。

是的,你关闭了两次FileStream。这是无害的。所以要两次处理它。多次处理发生。一次性部件的开发人员有责任正确处理多次处理,并且不会抛出异常 1

但是,按照约定,在已处置的Dispose()上调用FileStream是无操作的,对您的代码来说,同样的情况也是如此,它会在处置时调用Close()流。别这么做。

使用嵌套使用的建议修复很好。


1 The contract for IDisposable.Dispose要求:

  

如果多次调用对象的Dispose方法,则该对象必须忽略第一个之后的所有调用。如果多次调用Dispose方法,则该对象不得抛出异常。 <{1}}以外的实例方法可以在资源已经处理时抛出Dispose

此行为的正式用语是 idempotence