I went with most of the rest of my company last night to see Don Box give a talk. The conference he was speaking at was called "XML Web Services One", and none of us are particularly interested in web services, so we were relieved that the subject of his presentation turned out to be a preview of Whidbey, the next major version of .NET (current ETA is second half of 2004).
The big news to me was anonymous methods. I had expected them to be much like Java's implementation of anonymous classes, only at the method level; in other words, I could write something like this:
public void SomeMethod() { string label = "Foo"; this.Changed += new EventHandler(object sender, EventArgs args) { MessageBox.Show(label + " detected change in " + sender.ToString()); } }
and the compiler would expand it to something like this:
public void SomeMethod() { string label = "Foo"; __anon_1_label = label; this.Changed += new EventHandler(__Anon_1); } private string __anon_1_label; private void __Anon_1(object sender, EventArgs args) { MessageBox.Show(__anon_1_label + " detected change in " + sender.ToString()); }
While convenient, there's nothing really magic about what's going on here. It's just that the compiler would make up an opaque method name for you and move your method body there, while making copies of the caller's local variables for the method body to use. (OK, the code shown above wouldn't actually work because the same instance of __anon_1_label
would be shared among potentially many instances of the anonymous method--let's just pretend.)
Well, it turns out that C# anonymous methods are not anything like the above. They're way better. They're real closures.
The difference between a closure and the above is that a closure is directly wired into the scope of the enclosing block of code. In the above example, it means that after SomeMethod()
creates and registers the anonymous method, it could change the value of label and the anonymous method would "see" the new value when it gets called. Or, rather than just printing out a message, the anonymous method could change the value of label and the change would be reflected in the enclosing scope (assuming the enclosing scope is still around).
This opens up C# to all sorts of new styles of programming. For example, Ruby's beloved blocks and iterators will be possible:
List<i> list = new List<i>(); list.Add(1); list.Add(3); list.Add(5); int total = 0; list.each(new Visitor<i>(int i) { total += i; }); Console.WriteLine(total);
It's not as pretty as Ruby's syntax, but it's about as powerful and totally typesafe.
More fun with anonymous methods to come...