Ruby Influenced C#
Wednesday, May 7, 2008 at 09:07PM Before joining my current project I spent about 4 months working with Ruby every day, the first time I’d done so for a few years. It was a glorious time: uncluttered syntax, closures, internal iterators, and with open classes, the ability to extend the ‘core’ at will.
Today I’m working with C# and .NET, and I’ve noticed that those 4 months with Ruby have changed the way I’ve been writing code. Most noticeably, I’m using anonymous delegates a lot more. But that’s not all.
I’ve found myself aching to use the List<T>’s ForEach method; I’m now wired to use Ruby’s internal iterators where instead of
Listpeople = FindAllPeople(); foreach (Person person in people) { ... }
I can instead do
List<Person> people = FindAllPeople();
people.ForEach(delegate(Person person) {
Console.WriteLine(person.Name);
});
But, frequently I’m put off by the surrounding guff that’s needed to express the same and have almost always gone back to the more traditional external iterator-based approach. It’s simply too high-a-price to pay.
One of the largest smells I’ve noticed recently (to my mind) appears driven out of not having open classes and external iterators. If they were there, I’m sure people would use them. The result: all across the codebase, whenever you need to convert from type to another you’ll see
List<Person> people = FindAllPeople();
List<String> firstNames = new List<String>();
foreach (Person person in people) {
firstNames.Add(person.Name);
}
This smells to me. But it really, really smells from having used Ruby where I would previously have written something as succinctly as this:
find_all_people.collect {|person| person.name}
(I’m sure other languages could do equally good things- but I’m familiar with Ruby, before the Pythonists pounce :p)
Well, turns out that you can get nearly there with C# 2.0 and .NET 2.0 with the almost certainly underused ConvertAll method (also part of List<T>).
List<Person> people = FindAllPeople();
List<String> names = people.ConvertAll(delegate(Person person) {
return person.Name;
});
There’s still a fair bit of accidental complexity remaining- lot’s of delegate and type declarations.
C# 3.0 introduced lambda expressions and we can use that to bubble our soup down to a nice intentional broth even more. We can get rid of the delegate bumpf and let the compiler infer the type (we are still statically typed after all)
List<Person> people = FindAllPeople();
List<String> names = people.ConvertAll(person => person.Name);
Next step, we can also infer the types for our local variables:
var people = FindAllPeople(); var names = people.ConvertAll(person => person.Name);
Pretty nice. Most of the code is focused on the task at hand, and on expressing the necessary complexity (what it means to convert people to names). Guess learning a new language each year has it’s benefits.
I’ve got another bit of Ruby influenced C# refactoring to cover (a somewhat declarative way of removing switch statements), hopefully I’ll get that posted tomorrow!
c# 


Reader Comments (1)
How funny. I'm a graduate of the course, and I'm totally working on seminars and lessons around the concept of "programmers are people too". I think programmers are (by nature) even more emotionally and ego-driven people than most. It's part of what makes us great in our creative endeavors.
Understanding how to work well with team-members and how human factors affect development are so key. If you want to get the most out of people you work with (whether as peers, mentors, or people you supervise), Carnegie is the best (most pragmatic, to use a term of current interest) approach I've seen yet.
In other words... great column! :-)
(Google linked to you when I looked for "fine reputation", and then when I saw RoR it piqued my interest).