Bill Blogs in C#

Bill Wagner discusses C#, LINQ, and other items of interest

Creating Readable LINQ

Keith Elder wrote a post a post asserting (or at least proposing) that a more imperative syntax for a problem is more readable than a LINQ based C# 3.0 version. (See here for his post).  Well, that got my hackles up.  Some days, my hackles get up before I do, but I digress.

His example code as examining IP addresses for a machine. His poor example was this:

   1: string ipAddy = Dns.GetHostAddresses(Dns.GetHostName()).Single(i => ValidateIP4Address(i.ToString())).ToString();

(ValidateIP4Address is shown in Keith’s example, and is not repeated here).

I’ll agree with Keith on one point: that’s ugly code. Formatting is only part of it. It’s also not leveraging one of the features that make LINQ readable: query expressions. It uses two different conversions from each IP address to a string.  Much of the core logic is hidden.

Let’s try this instead:

   1: var ipAddy = (from address in Dns.GetHostAddresses(Dns.GetHostName())
   2:               let addressLabel = address.ToString()
   3:               where ValidateIP4Address(addressLabel)
   4:               select addressLabel).First();

The first line of the query defines the source: Host addresses.

The second line defines a local variable to cache the string representation of the address.

The third line defines the filter condition: A valid IP4 address.

And the fourth line defines the result: A single string, the first in the sequence

I’ll agree that if you haven’t looked at LINQ code very much, this can still appear hard to read. But that’s a short-term argument: If you’re reading my blog, you're a developer, and you should be learning new features in whatever language you are using.

Some of Keith’s concerns are very valid: pulling out the latest new features just to use them and experiment with whatever looks interesting will create bad code. But there is a lot to be gained by using the new features carefully, and adding them in the appropriate manner, and following the best idioms for the newer features.

There’s plenty of resources to help you. Use them, and discuss readability with your peers. It’s the only way you’ll know what other developers will understand.

Published Fri, Oct 10 2008 12:40 AM by wwagner

Comments

# re: Creating Readable LINQ@ Friday, October 10, 2008 8:26 AM

Bill,

I got the impression reading your post that you "skimmed" my article and didn't really get what it was I was getting at.

I used the Lambda example first just to prove a point that C# 3.0 can look god awful using the new features of the language.  

The LINQ example (did you get that far in the article?) won out in readability and then later on through discussions with some other developers was simplified even more by adding an extension method.  Here's a quote:

"For me the LINQ version above is the most interesting and I think the simplest to understand for someone looking at the problem for the first time.  I think it expresses more of the “intent” of what I was doing."

The whole point of this is C# 3.0 can be written where it is unreadable (lambda as an example) but it can also make the code 200% more readable than the old way by combining several features, not just one.

Although you say you disagree, I know we both agree because we both agree the LINQ example is the most readable.  Hugs all around :)

Cheers.

-Keith

# re: Creating Readable LINQ@ Friday, October 10, 2008 10:16 AM

Your not being fair to Keith. His post identifies 4 different styles of coding this functionality and he settles on a LINQ based approach almost identical to the one you propose as the most readable option. In your rush to lambast critics of new syntax styles did you forget to read to the conclusion?

by More careful reader?

# re: Creating Readable LINQ@ Friday, October 10, 2008 10:18 AM

Being able to use both correctly, and when to use, is more important  The query type LINQ structure is great for one off selects or say easy selects like the one you have here, but can get really verbose when trying to say select to separate lists and concatenate them.  That or with simple situations like:

var test = from item in ItemList

          select item.Property;

Using a method and Func makes is a lot less wordy:

var test = ItemList.Select(selectItemProperty);

You could point out that I still have to declare the Func somewhere, but that's fine.  I can look at that one line (With a well named Func) and tell what it's doing.

Also, something that needs to be pointed out is that there seems to be a hang up on how "ugly" lambda expressions are.  I admit they can add length and do prove difficult to find proper formatting.  However, this is where Funcs and Actions really shine.  This expression:

string ipAddy = Dns.GetHostAddresses(Dns.GetHostName()).Single(i => ValidateIP4Address(i.ToString())).ToString();

Could be transformed into this easily:

string ipAddy = Dns.GetHostAddresses(Dns.GetHostName()).Single(validateIP4Address).ToString();

Which leaves it a lot less "messy" looking.

On the "don't use it just to use it" idea, I admit that just throwing something in can be reckless, how can you know when to use it if you don't blatantly experiment with it?

by Sean

# re: Creating Readable LINQ@ Saturday, October 11, 2008 10:01 PM

Hi. I just wanted to say that lines 2 and 4 in the sample Linq query are black text on black background.  I can only see the code by highlighting the lines of text.  Lines 1 and 3 are okay.  Maybe a different color scheme might be easier on the eyes ... the contrast of white on black always startles my eyes, for whatever reason.  Thank you.