8

考虑以下代码:

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

2 回答 2

3

这种特殊情况的解决方案是调用StreamWriter 构造函数的重载,让您告诉它不要释放底层流

不幸的是,这仅适用于 .Net 4.5;否则你将不得不做你已经在做的事情。

另外,请参阅此线程:有什么方法可以在不关闭其 BaseStream 的情况下关闭 StreamWriter?

顺便说一句,当我尝试时,OP 中的代码不会导致异常!

下面的示例假设存在一个名为“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");
                }
            }
        }
    }
}
于 2013-03-13T13:48:17.193 回答
3

在这种情况下,FxCop 与 .NET Framework 中的设计选择非常不一致。问题是由 StreamWriter 假设流的所有权引起的。这通常是一种“落入成功之坑”的设计选择,大多数程序员会认为关闭 StreamWriter 足以处理流。特别是当他们使用 Close() 而不是 Dispose() 时。

在绝大多数情况下效果很好。大多数情况下,一种非常有问题的特殊用法是 CryptoStream。当底层流在 CryptoStream 被刷新和处置之前关闭时,需要刷新并且无法诊断的故障的类。FxCop 警告适用的情况,尽管它太神秘而无法轻松识别特定问题;)

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

在这种特定情况下,FxCop 警告毫无用处。所有 .NET Framework 提供的 Dispose() 方法实现都是安全的。FxCop 应该自动抑制 .NET 框架代码的此类警告。但不是,微软也使用它。.NET 框架源代码中有很多[SuppressMessage] 属性。

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

使用 [SuppressMessage] 属性关闭警告。

于 2013-03-13T16:00:40.503 回答