C# 防止多次处置对象
考虑以下代码:C# 防止多次处置对象,c#,.net,stream,dispose,msdn,C#,.net,Stream,Dispose,Msdn,考虑以下代码: using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate)) { using (StreamWriter writer = new StreamWriter(stream)) { // Use the writer object... } } 当writer流被处理时,它在内部处理文件流流 除了在finally条款中处理外部使用的流之外,是否还有其他设计
using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
using (StreamWriter writer = new StreamWriter(stream))
{
// Use the writer object...
}
}
当writer
流被处理时,它在内部处理文件流流
除了在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();
}
这种特殊情况的解决方案是调用 不幸的是,这只适用于.NET4.5;否则你将不得不做你已经在做的事情 另外,请参见此线程: 顺便说一句,OP中的代码在我尝试时不会导致异常 以下示例假定存在名为“C:\TEST”的文件夹:
在这种情况下,FxCop与.NET Framework中的设计选择存在很大的分歧。问题是由StreamWriter假设流的所有权引起的。一般来说,这是一种“落入成功陷阱”的设计选择,大多数程序员会认为关闭StreamWriter就足以处理流。尤其是当他们使用Close()而不是Dispose()时 这在绝大多数情况下都很有效。在大多数情况下,CryptoStream是一种非常有问题的特殊用法。当底层流在加密流被刷新和释放之前关闭时,需要刷新和不可诊断的故障的类。在这种情况下,FxCop警告是合适的,尽管它太神秘,无法轻易识别特定问题;) 一般情况下,程序员编写了自己的Dispose()方法,却忘了确保它不会被多次调用。这正是FxCop警告想要引起注意的地方,否则它不够聪明,无法看到Dispose方法实际上是安全的 在这种特定情况下,FxCop警告毫无用处。所有.NET Framework提供的Dispose()方法实现都是安全的。FxCop应该自动抑制.NET framework代码的此类警告。但事实并非如此,微软也在使用它。在.NET framework源代码中有大量的[SuppressMessage]属性 处理警告太难看了,而且容易出错。而且毫无意义,因为实际上没有什么问题。请记住,FxCop只是一个诊断工具,旨在生成“您是否考虑过这个”消息。如果你无视规则,不是警察会把你关进监狱。这是编译器的工作
使用[SuppressMessage]属性关闭警告。根据Microsoft的说法,您应该能够多次调用同一对象的Dispose()。@MatthewWatson,引用Microsoft on的引用会很好。@MatthewWatson当第1次使用时,尝试处理一个已准备就绪的对象,它会导致错误否,它不是试图处理一个已经被处理的对象,而是试图使用那个对象(通过关闭/刷新它)。@Miky:看,这说明如果一个对象的dispose方法被调用多次,那么该对象必须忽略第一次调用之后的所有调用。你为什么要谈论异常?这是一个代码分析警告。只是一个信息:在我的例子中,我刚刚注意到即使是.net 4.5也不会帮助我,因为我的例子中的“内部”流是XmlTextWriter,它没有leaveOpen标志!知道微软使用SuppressMessage来压制其警告真的很有趣。许多人将这些规则视为编程圣经。在我的例子中,使用stringwriter和textxmlwriter更为复杂,因此我必须将字符串保存在tempvariable中,然后才能按照msdn上的建议将stringwriter设置为null。
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");
}
}
}
}
}