The power of closures in C# 2.0
Martin Fowler (obligitary Fowlbot namedrop) recently blogged about the power of closures in languages that support them. It’s worth remembering that C# 2.0 has true closure support in the form of anonymous delegates. This includes reading and modifying variables outside the context of the closure – unlike Java’s anonymous inner classes.
Just for kicks, I’ve rewritten all of the examples Martin’s Ruby examples in C# 2.0. This makes use of the improved APIs in .NET 2.0 pointed out by Zohar.
Ruby | C# 2.0 |
def managers(emps) return emps.select {|e| e.isManager} end |
public List<Employee> Managers(List<Employee> emps) { return emps.FindAll(delegate(Employee e) { return e.IsManager; } } |
def highPaid(emps) threshold = 150 return emps.select {|e| e.salary > threshold} end |
public List<Employee> HighPaid(List<Employee> emps) { int threshold = 150; return emps.FindAll(delegate(Employee e) { return e.Salary > threshold; }); } |
def paidMore(amount) return Proc.new {|e| e.salary > amount} end |
public Predicate<Employee> PaidMore(int amount) { return delegate(Employee e) { return e.Salary > amount; } } |
highPaid = paidMore(150) john = Employee.new john.salary = 200 print highPaid.call(john) |
Predicate<Employee> highPaid = PaidMore(150); Employee john = new Employee(); john.Salary = 200; Console.WriteLine(highPaid(john)); |
The code difference between the languages isn’t that difference. The C# 2.0 code is obviously longer (though not a lot) because:
- C# 2.0 is staticly typed (let’s not get started on the static vs dynamic debate).
- C# 2.0 requires the ‘delegate’ keyword.
- Ruby allows you to ignore the ‘return’ keyword.
You can try this stuff out yourself by playing with Visual C# Express.
Cool, but what’s with the capitalized method names? ICK!!!
Here is a sample comparison of anonymous delegates in C# 2.0 with anonymous inner classes in Java.
C# 2.0
int total = 0;
order.EachItem(delegate(Item item) {
total += item.Price;
}
Console.WriteLine(“Total of order is {0}”, total);
Java
final int[] total = { 0 };
order.eachItem(new OrderBlock() {
public void handle(Item item) {
total[0] += item.getPrice();
}
});
System.out.println(“Total of order is ” + total[0]);
This is something I end up doing a lot, and I cringe everytime. The anonymous bloat I don’t mind so much, but the final array hack is what really gets me. This is necessary because any local variable outside the scope the of the inner must be final, so the only way to write to it is to use an array. Thankfully IDEA always automagically sorts this out for me, but it’s still confusing for someone who is later trying to understand the code.
I said many times: c# 2.0 is a kind of statically typed ruby. Even the icollection apis wich gets anonimous delegates as parameters really resemble ruby’s Enumerable.
If you want use scripting languages, go with Groovy. This have very extended closure support.
“The C# 2.0 code is obviously longer (though not a lot) because:
C# 2.0 is staticly typed (let’s not get started on the static vs dynamic debate).”
No, not quite the right reason. C# is longer specifically because it uses manifest typing.
Eeee! The code runs all over the sidebar. Unreadable even at 1024 px width!
Try putting such code blocks in a div with the style “overflow:auto” set
just to remind that JScript supports this technique
small sample:
function A(D) {
var C = 10;
if (D == 1) {
B = function () {
WScript.Echo(C);
}
C = 11;
}
else
C = 12;
B();
C = 13;
}
var
C = 90;
A(1);
A();
B();
C# Version 2.0 Specification
C# Version 2.0 Specification
The example code is wrong, I think. Shouldn’t the FindAll example actually be:
public List Managers(List emps) {
return emps.FindAll(delegate(Employee e) {
return e.IsManager;
} );
}
Note the additional round bracket and semicolon at the end of the return statement. The code doesn’t look quite so clean now, unfortunately.
I’ve put boo versions of these examples here:
http://docs.codehaus.org/display/BOO/Martin+Fowler%27s+closure+examples+in+boo
Boo is a new object oriented statically typed programming language for the Common Language Infrastructure with a python inspired syntax and a special focus on language and compiler extensibility.
http://boo.codehuas.org
Sorry the second link above to boo should be:
http://boo.codehaus.org/
Closures in C# 2.0
Closures in C# 2.0
I would like to check this out, but I can’t read the C# because it drools out into the right sidebar.
Minor note by a rubyist – the Ruby code examples don’t make use of omitting the return keyword. If you used return inside a closure, it would return from the method it was defined in.
Collection closure method
Collection closure method
Collection closure method
Collection closure method
Please God fix the messed up tables created by SiteMash and UnmoveableType so I can read this example.
Quote:
|The C# 2.0 code is obviously longer (though not a lot) because:
| * C# 2.0 is staticly typed (let’s not get started on the static vs
| dynamic debate).
Static typing is a bad excuse for longer code. It’s not obvious at
all. Look at this Haskell example:
f x = (\y -> x + y)
It’s a closure (see ).
Nevertheless Haskel is a statically typed language (see table “Type
system cross reference list” in
).
Regards
Thomas
Sorry that I’ve to post it again, but the Blog software skipped the
URLs because of the surrounding angle brackets.
Quote:
|The C# 2.0 code is obviously longer (though not a lot) because:
| * C# 2.0 is staticly typed (let’s not get started on the static vs
| dynamic debate).
Static typing is a bad excuse for longer code. It’s not obvious at
all. Look at this Haskell example:
f x = (\y -> x + y)
It’s a closure (see http://www.haskell.org/hawiki/Closure).
Nevertheless Haskell is a statically typed language (see table “Type
system cross reference list” in
http://en.wikipedia.org/wiki/Dynamic_typing ).
Regards
Thomas
Essential C# 2.0
http://www.awprofessional.com/bookstore/product.asp?isbn=0321150775&rl=1 (sample chapter “Generics”
Essential C# 2.0 is a clear, concise guide to C#—including the features new to C# 2.0. The book clearly presents material for beginners and experts and provides contrasts and comparisons between C# and other languages. The C# language is covered comprehensively and each important construct is illustrated with succinct code examples. Complete code examples are available online. Mark Michaelis has organized the material for quick access. Graphical “mind maps” at the beginning of each chapter show what material is covered and how each topic relates to the whole.
Following the C# introduction, readers will learn about
• C# primitive data types, value types, reference types, type conversions, and arrays
• Operators and control flow, loops, conditional logic, and sequential programming
• Methods, parameters, exception handling, and structured programming
• Classes, inheritance, structures, interfaces, and object-oriented programming
• Well-formed types, operator overloading, namespaces, and garbage collection
• Generics, collections, and iterators
• Reflection, attributes, and declarative programming
• Threading, synchronization, and multi-threaded patterns
• Interoperability and unsafe code
• The Common Language Infrastructure that underlies C#