Cleaning up external resources
Bob Congdon has a post up on the difficulties of cleaning up external resources in Java if exceptions get thrown while they are in use. He points to a C# feature that ensures that such resources will be finalized, the using statement:
using (TextWriter tw = File.CreateText("log.txt")) {
tw.WriteLine("Foo");
// Other stuff
}
Apparently, the compiler expands that. In Smalltalk, we don't need a language feature for that - we have the #ensure: method. It looks like this:
stream := 'someFile' asFilename writeStream. [stream nextPutAll: 'Foo'. "other code here"] ensure: [stream ifNotNil: [stream close]].
#ensure takes a block (closure) as an argument, and will execute regardless - if there are exceptions inside the block it's sent to or not. It's a very clean way to make sure that necessary code runs, when you aren't particularly concerned with the exact nature of any exceptions that pop up.


Comments
C# expansion
[] February 13, 2006 12:29:07.726
The using(...) you list above is really sugar for the more verbose try {} finally {}
Unless I'm forgetting my Smalltalk, the ensure: block essentially translates to try{} finally{} in C# (and in Java).
Also in Ruby
[Mr. Big] February 13, 2006 13:13:17.727
[] February 13, 2006 13:51:35.770
This should be part of the standard library
[Wilkes Joiner] February 13, 2006 21:32:37.616
In Ruby you can say:
File.open('somefile.txt', 'w') do | f |
... do some stuff with the file ...
end
This guarantees that the file will be closed. There is no reason that this can't be done in Smalltalk:
File class>>openForWriting: aString do: aBlock
stream := aString asFilename writeStream.
It's actually easier in Java
[Matthias] February 14, 2006 2:29:04.059
Bob just hasn't figured it out. You put the try after the variable declaration, it becomes much less clunky than his version and no less right:
Re: It's actually easier in Java
[Christian Ullenboom] February 16, 2006 2:43:28.462
Sorry Matthias but you need a second (ugly) try/catch around close (or a throws in the method definition, o.k.)
OutputStream os = new FileOutputStream("someFile");try { os.write(bytes); } finally { try {os.close(); } catch (IOException e ){} }
BTW: I like IOUtils from Jakarta Commons IO.