From: "Jörg W Mittag" Date: 2010-01-22T06:20:22+09:00 Subject: Re: Ruby equivalent of C# "using keword" and IDispose Peter Alvin wrote: > What is the most expedient way to do this C# construct in Ruby? > > C#: using (myObj = new MyClass()) { > // misc code here > } //MyClass.Dispose automatically called here > > I wish to put stuff in MyClass.Dispose() to release resources... it must > always be called. In a language with higher-order procedures like Ruby, adding a special language construct for this is completely unnecessary. You just write a method which accepts a piece of code as an argument, acquires the resource, runs the piece of code and subsequently releases the resource. This is the well-known "with-foo" pattern from Lisp, basically. In Ruby, we generally use a factory-ish class method like so: class DatabaseConnection def self.use(*args) yield handle = new(*args) ensure handle.close end end This is how usage would look like: DatabaseConnection.use('/path/to/sqlite.db') do |conn| conn.exec 'SELECT blah FROM blurb WHERE foo = 42;' conn.exec 'INSERT something INTO somewhere;' end This pattern is for example used by IO.open in the standard library: File.open('/path/to/file', 'w+') do |f| f.puts 'Hello, World' end The two main differences between the two methods are: * in the Ruby version, the acquisition of the resource is hidden away inside the method, whereas in C#, the user is responsible for creating the resource. (You could, of course, write a generic method that simply takes any resource as a parameter. That's just not the normal style in Ruby.) * in the C# version, there is a standardized agreement over what the name of the method for releasing the resource is (the Dispose() pattern) and there is even a type for it (the IDisposable interface) Here's what a more C# style implementation in Ruby would look like: def using(handle) yield handle ensure handle.dispose end using(MyClass.new) do |my_obj| # misc code here end # MyClass#dispose automatically called here BTW: you can do that in C#, too, now. It's just that before lambda expressions, local variable type inference and anonymous types were introduced in C#, it would have been a lot of typing (in both senses of the word). This is what the opposite would look like (i.e. Ruby style implemented in C#): class DatabaseConnection { static T use(string connection, Func block) { var handle = new DatabaseConnection(connection); try { return block(handle); } finally { handle.Dispose(); } } } And this is how you use it: DatabaseConnection.use("/path/to/db", (conn) => { // misc code here }); // MyClass.Dispose automatically called here (If you don't want to return a value, lose the T and replace Func with Action.) jwm