views:

429

answers:

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

Using the above code works perfectly. However, when I shorten it to:

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

I get the following exception when I try to deserialize the users.xml file in the same test: The process cannot access the file 'users.xml' because it is being used by another process.

The cause seems to be that the the File.Create method returns an opened FileStream, that I cannot close as I do not hold onto a reference of it.

My bad, or Microsoft's? ;-)

+9  A: 

The problem is that in your second example you open a file handle that you never dispose of, so the second time you call your method it will throw the exception you are describing. The first snippet is the preferable way (You could remove the file_stream.Close() bit - it will be automatically called by Stream.Dispose()).

Darin Dimitrov
Thanks, my bad it is then.
Dabblernl
A: 

If you didn't have the "using" statement, but retained the close, you'd have been ok.

[Edit: Added try...finally, thanks 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()
}

In that case, however, Dispose is preferable because it knows all the actions it must take to clean up, including close (and any thing else).

Nader Shirazie
don't forget the try...finally!
Cheeso
wow that using syntax is convenient... thanks Cheeso
Nader Shirazie
+1  A: 

You should serialize in a try finally block so that you can make sure that the file is closed/disposed regardless of success or failure. This is what the using keyword does for you.

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

File.Create should be placed outside of the try block as shown in my earlier answer. If you put it inside the try block, you need to check fs for a null reference before closing. The following shows the corrected code but my first answer is much better since you can avoid this check.

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()
}
anonymous