防止多次处置物体

本文关键字: | 更新日期: 2023-09-27 18:03:46

考虑以下代码:

using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
    using (StreamWriter writer = new StreamWriter(stream))
    {
        // Use the writer object...
    }
}

writer流被处理时,它会在内部处理FileStream stream

除了MSDN建议在finally子句中处理外部使用的流之外,是否还有其他设计:

Stream stream = null;
try
{
    stream = new FileStream("file.txt", FileMode.OpenOrCreate);
    using (StreamWriter writer = new StreamWriter(stream))
    {
        stream = null;
        // Use the writer object...
    }
}
finally
{
    if(stream != null)
        stream.Dispose();
}

防止多次处置物体

在这种情况下,FxCop与。net框架中的设计选择是非常不一致的。这个问题是由StreamWriter假定流的所有权引起的。这通常是一种"失败"的设计选择,大多数程序员会认为关闭StreamWriter就足以处理流。特别是当他们使用Close()而不是Dispose()时。

在绝大多数情况下都很有效。大多数情况下,有一个特殊的用法非常有问题,那就是CryptoStream。在刷新和处置加密流之前关闭底层流时需要刷新且无法诊断的故障的类。在这种情况下,FxCop警告是合适的,尽管它太过神秘,无法轻易识别特定的问题;)

以及程序员编写自己的Dispose()方法并忘记使其不会被多次调用的一般情况。这就是FxCop警告要引起注意的,否则它不够聪明,无法看到Dispose方法实际上是安全的。

在这种特殊情况下,FxCop警告是无用的。所有。net框架提供的Dispose()方法实现都是安全的。对于。net框架代码,FxCop应该自动抑制这类警告。但是没有,微软也在使用它。在。net框架的源代码中有大量的[SuppressMessage]属性。

绕过警告是很难看的,而且容易出错。而且毫无意义,因为实际上没什么问题。请记住,FxCop只是一个诊断工具,旨在生成"您是否考虑过这个"消息。当你无视规则时,警察不会把你关进监狱。这是编译器的工作。

使用[SuppressMessage]属性关闭警告

这种特殊情况的解决方案是调用StreamWriter构造函数的重载,该构造函数允许您告诉它不要处置底层流。

不幸的是,这只适用于。net 4.5;否则你就得做你已经在做的事了。

也,看看这个线程:有没有办法关闭一个StreamWriter而不关闭它的base流?

顺便说一下,OP中的代码NOT在我尝试时导致异常!

下面的示例假设存在一个名为"C:'TEST"的文件夹:

using System;
using System.IO;
namespace Demo
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            // This does NOT cause any exceptions:
            using (Stream stream = new FileStream("c:''test''file.txt", FileMode.OpenOrCreate))
            {
                using (StreamWriter writer = new StreamWriter(stream))
                {
                    writer.Write("TEST");
                }
            }
        }
    }
}
相关文章:
  • 没有找到相关文章