2009-05-17 41 views
6
 using (var file_stream = File.Create("users.xml")) 
     { 
      var serializer = new XmlSerializer(typeof(PasswordManager)); 
      serializer.Serialize(file_stream, this); 
      file_stream.Close(); 
     } 

使用上面的代码完美地工作。然而,当我把它缩短:Xml序列化无需处理

  var serializer = new XmlSerializer(typeof(PasswordManager)); 
      serializer.Serialize(File.Create("users.xml"), this); 

我出现以下情况例外,当我尝试反序列化在同一个测试Users.xml文件: 该进程无法访问文件“users.xml中”,因为它是被另一个进程使用。

原因似乎是File.Create方法返回一个打开的FileStream,我无法关闭,因为我没有保留它的引用。

我的不好,还是微软的? ;-)

+0

这里有一个潜在的概念,你错过了(这很容易做到) - 阅读使用iDisposable接口的对象。 – overslacked 2009-05-17 20:28:32

回答

11

问题是,在你的第二个例子中,你打开一个你永远不会处理的文件句柄,所以当你第二次调用你的方法时,它会抛出你描述的异常。第一个片段是更好的方法(您可以删除file_stream.Close()位 - 它将由Stream.Dispose()自动调用)。

+0

谢谢,我的坏处是。 – Dabblernl 2009-05-17 21:17:09

0

如果您没有“使用”声明,但仍保留关闭状态,则表示您确定。

[编辑:新增尝试......最后,感谢cheeso]

var serializer = new XmlSerializer(typeof(PasswordManager)); 
FileStream fs; 
try 
{ 
    fs = File.Create("users.xml"); 
    serializer.Serialize(fs, this); 
} 
finally 
{ 
    fs.Close(); // or fs.Dispose() 
} 

在这种情况下,然而,处置是可取的,因为它知道所有它必须采取清理行动,包括关闭(以及其他任何东西)。

+0

别忘了试试...终于! – Cheeso 2009-06-29 19:06:39

2

您应该序列化最后尝试块,以便无论成功或失败都可以确保文件已关闭/处置。这是使用关键字为您所做的。

var serializer = new XmlSerializer(typeof(PasswordManager)); 
var fs = File.Create("users.xml"); 
try { serializer.Serialize(fs,this); } 
finally { fs.Close(); } 
0

File.Create应放置在try块之外,如我在前面的答案中所示。如果你把它放在try块中,你需要在关闭前检查fs作为空引用。以下显示了更正后的代码,但我的第一个答案要好得多,因为您可以避免此检查。

serializer = new XmlSerializer(typeof(PasswordManager)); 
FileStream fs; 
try 
{ 
    fs = File.Create("users.xml"); 
    serializer.Serialize(fs, this); 
} 
finally 
{ 
    if (fs != null) // in case File.Create fails 
     fs.Close(); // or fs.Dispose() 
}