Skip to content

Expressive power of LINQ extension methods

September 21, 2010

I really dig the extension methods provided by the System.Linq namespace in .NET.  They work on anything you can enumerate, and I find myself rarely writing loops anymore.  I wish more developers used them–when reviewing code I see lots of examples that may be refactored to more succinctly express what they need.

Here’s a real example from a project that I recently reviewed (variable names were changed to hide what we’re working on).  This block needs to extract values that are stored as integers in one object called “prof”, and copy them to a local array, while converting the integers to strings.

string[] ids= new string[prof.Count];
int index= 0;
IEnumerator enumerator = prof.Values.GetEnumerator();
while (enumerator.MoveNext())
    ids[index++] = enumerator.Current.ToString();

The data behind integer “Values” could not simply be copied, because the conversion to string was required, so a manual loop was created instead.  This is where LINQ extensions come in.  They work on enumerations, so you don’t need to write a loop, and the “Select” function allows transforming the data type using a lambda function.  The same 5 lines of code are rewritten as:

string[] ids= prof.Values.Select(id => id.ToString()).ToArray();

I find the rewritten code not only more succinct, but easier to read and maintain.

Here’s another example from the same review.  Here a function takes a URL, and returns only the first 8 bytes of its md5 hash.  The code as I found it looked like this:

byte[] Url2Hash(string url)
{
    byte[] md5FixedSizeByteArray = new byte[8];
 
    // Get the MD5 byte representation.  It has 16 bytes.
    byte[] md5ByteArray = md5.ComputeHash(encoding.GetBytes(url));
 
    // Copy the first 8 bytes.
    Array.Copy(md5ByteArray, 0, md5FixedSizeByteArray, 0, 8);
 
    return md5FixedSizeByteArray;
}

Again, this is a one liner using LINQ. The value returned from hash computation is an array, so it may be enumerated by the “Take” function to grab the first 8. And we’re done:

byte[] Url2Hash(string url)
{
    return md5.ComputeHash(encoding.GetBytes(url)).Take(8).ToArray();
}

These are just simple examples (albeit not toy code, these were from real projects) that barely begin to demonstrate what power is available from LINQ functions: it’s possible to sort, filter, aggregate and collect statistics, intersect, etc. Here’s a page that demonstrates many of the possibilities.

Leave a Reply

Your email address will not be published. Required fields are marked *