fail. Either close the stream in the catch block directly as well, or
keep a flag of whether or not to delete the file, set it in the catch,
and do it in the finally.
Peahaps I misunderstand your idea, but I contrive to do it vice-versa -- set
up the flag in finally and rollback in catch:
enum RollbackMarker {none, file, db_record};
RollbackMarker rbm = RollbackMarker.none; // rollback marker
try {
// create a file
Stream fs = new FileStream(name, FileMode.Create);
try {
// write file
} finally {
fs.Close(); // first, we must close the file
rmb = RollbackMarker.file; // 2nd, we must remove it if
failure
}
// add DB entry
Entry entry = db.insert(data);
rbm = RollbackMarker.db_record;
.. make more construction-allocations
} catch (Exception e) {
// failure, rollback the allocations
log("rolling back since " + rbm);
switch (rbm) {
...
case RollbackMarker.db_record: File.Delete(); goto case
RollbackMarker.file; // why the hell did MS refuse the downfalls?
case RollbackMarker.file: db.remove(entry); break;
}
throw; // re-throw
}
Note, the rollback marker in the finally section.Whether file I/O success or
error we must complete the file creation by closing it and and note that the
file has been created. Resources must be closed only if their
constructor/allocator has succeeded.Therefore, I set up the marker after
construction.