Closing a file without using using
I have a class which reads data from one file stream and writes to another. I am concerned about closing the streams after the processing has finished in closeFiles().
How would you handle the possibility that the dispose of one stream may throw an exception stopping the dispose of the other stream from being called.?
Should I be calling close and dispose on the streams or just one?
What happens if I catch any errors from the stream disposes and then continue with moving and deleting of the files as shown in lastOperation()?
In a perfect world I'd like to use a using statement in a c++ style initialisation list but I'm pretty sure that's not possible in c#.
EDIT : thanks for the quick responses guys. So what I should be doing is deriving from IDisposable and then change the constructor and add the two disposing methods like this?:
~FileProcessor()
{
Dispose(true);
}
public void Dispose()
{
D开发者_StackOverflowispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
sw.Flush();
}
closeFiles();
disposed = true;
}
}
This is basically what I'm doing:
class FileProcessor
{
private string in_filename;
private string out_filename;
private StreamReader sr;
private StreamWriter sw;
bool filesOpen = false;
public FileProcessor(string filename)
{
in_filename = filename;
out_filename = filename + ".out";
openFiles();
}
~FileProcessor()
{
closeFiles();
}
private void openFiles()
{
sr = new StreamReader(in_filename);
sw = new StreamWriter(out_filename);
filesOpen = true;
}
private void closeFiles()
{
if (filesOpen)
{
sr.Close();
sw.Close();
sr.Dispose();
sw.Dispose();
filesOpen = false;
}
}
/* various functions to read, process and write to the files */
public void lastOperation()
{
closeFiles();
File.Delete( in_filename );
Directory.Move(out_filename, outdir + out_filename);
}
}
Your FileProcessor class should not have a destructor. It is of no use but it is expensive.
It should have a Dispose()
(and implement the IDisposable interface) to call closeFiles().
And like @marcelo answered, Stream.Dispose() should not throw. You can rely on this for BCL classes.
But you should check each Reader/Writer for null, in case the first one opened but the second one failed:
if (sr != null) sr.Dispose();
if (sw != null) sw.Dispose();
Your filesOpen
can't cover both.
I think it is a good practise to have your class implements IDisposable
interface if you are using IDisposable object inside it.
Then, you should make sure that, in your Dispose()
implementation, don't throw exceptions. If every object you dispose makes this guarantee, your client will be safe.
Dispose methods should never throw exceptions. There's even a code analysis tool warning for this.
In C#, using
does exist. The object provided to the using statement must implement the IDisposable interface. This interface provides the Dispose method, which should release the object's resources.
If your StreamReader and StreamWriter implement IDisposable, you can put them in a using block, and they will be disposed of cleanly when you have finished with them.
using(var sr = new StreamReader(in_filename)) {
// Perform reader actions
}
// Reader will now be disposed.
精彩评论