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.