没有处置的Xml序列化

时间:2009-05-17 20:15:33

标签: .net xml-serialization idisposable

       using (var file_stream = File.Create("users.xml"))
        {
            var serializer = new XmlSerializer(typeof(PasswordManager));
            serializer.Serialize(file_stream, this);
            file_stream.Close();
        }

使用上面的代码非常有效。但是,当我把它缩短为:

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

当我尝试在同一测试中反序列化users.xml文件时,我收到以下异常: 该进程无法访问文件'users.xml',因为它正由另一个进程使用。

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

我的坏,还是微软? ; - )

4 个答案:

答案 0 :(得分:11)

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

答案 1 :(得分:2)

您应该在 try finally 块中序列化,这样您就可以确保无论成功与否,都会关闭/处置该文件。这就是使用关键字为您所做的事情。

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

答案 2 :(得分: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()
}

但是,在这种情况下,Dispose更可取,因为它知道所有清理时必须采取的行动,包括关闭(以及其他任何事情)。

答案 3 :(得分: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()
}