Last listened to The Getaway by Immortal Technique (on 10 Mar 2010, 14:39)

Using LINQ to reduce code and increase code readability

Simply put: using LINQ enables you to do more, with less code.

I bought the LINQ pocket reference book (a great book, and a great format) and have read the whole thing several times. One of the examples is this scenario: we have a list of names, and we want to erase the vowels, and then get the resulting names that have more than 2 characters, and order them alphabetically (yes, hardly a realistic every day scenario - but a good example nevertheless!).

string[] names = { "Harry", "Tom", "Dick", "Mary", "Jay" };

The book goes on to say that using LINQ we can solve this problem in both comprehension and lambda syntax. Firstly, my preference, comprehension syntax:

var query = from n in names
            select Regex.Replace(n, "[aeiou]", "")
            into noVowel
            where noVowel.Length > 2
            orderby noVowel
            select noVowel;

// Result: { "Dck", "Hrry", "Mry" }
return query.ToList();

But the same thing can be done (arguably) more elegantly and succinctly using lambda syntax:

var query = names.Select (n => Regex.Replace(n, "[aeiou]", ""))
                 .Where  (n => n.Length > 2)
                 .OrderBy(n => n);

// Result: { "Dck", "Hrry", "Mry" }
return query.ToList();

Nowadays, after I became hooked on LINQ, I wouldn't consider trying to do this without LINQ. But this example got me wondering: just how much time am I saving? How many lines of code have I done away with? I've knocked up another solution without using the System.Linq namespace:

List results = new List();

// Get the names with more than 2 consonants
foreach (string n in names)
{
    string noVowel = Regex.Replace(n, "[aeiou]", "");

    if (noVowel.Length > 2)
    {
        results.Add(noVowel);
    }
}

// Sort the results if necessary
if (results.Count > 1)
{
    results.Sort();
}

// Result: { "Dck", "Hrry", "Mry" }
return results;

By using LINQ we're writing less than half the code we would normally write. It's also important to note several things here (and each one of these points follows on from the one before it):

  1. Both forms of LINQ solve the problem in a single expression, or statement.
  2. The LINQ expression itself is undoubtably more semantically meaningful (to humans) than a cumbersome set of foreach loops and if statements - i.e. we're moving towards code that reads more like English than code!
  3. By having our code more readable, and less of it, as developers we can express our intent faster, more efficiently, and have our code make "more sense" than ever before.

LINQ now makes C# code more readable and more powerful at the same time, and that's a truly awesome thing.

Performance of foreach loops vs. LINQ

After discovering LINQ, it's tempting to use it all the time, even in place of a basic foreach loop, but I've only recently looked into the performance of LINQ compared with the "old" C# coding techniques we're all used to.

From what I have tested myself and read elsewhere, it seems that LINQ is slightly slower than for example foreach loops when doing basic operations. Let's say we have the the following class:

public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public double Salary { get; set; }
}

Now let's assume we want to get all Employees that have a salary greater than 50000.00. To do this using a traditional foreach loop we would do something similar to this:

List employees = GetEmployees();
List highEarners = new List();

foreach (Employee employee in employees)
{
    if (employee.Salary > 50000.00)
    {
        highEarners.Add(employee);
    }
}

return highEarners;

The LINQ equivalent would be this:

List employees = GetEmployees();

var highEarners = from employee in employees
                  where employee.Salary > 50000.00
                  select employee;

highEarners.ToList();

I tested the foreach loop and its LINQ equivalent against a collection of a million items and found that the LINQ version was anywhere between 1.5 to 3 times slower. Another article testing the same thing (LINQ vs Loop - A performance test) pointed out (in the comments) that you can seriously slow down your LINQ query (make it upto 10 times slower) by accidentally writing your LINQ statement the wrong way. Write LINQ with care.

If you've replaced a simple foreach with some LINQ, you've slowed things down but you're probably not going to get a noticable performance hit unless you're dealing with many millions of items - but it's definately not beneficial to use LINQ in this scenario.

In an interview recently I mentioned this performance hit, and the interviewer asked me "well then when should you use LINQ?" and I'm going to answer that in my next couple of posts, because it's a question I've been wondering about a lot recently.

LINQ under the microscope

Over the next few weeks I'm going to be blogging about LINQ, the feature of .NET Framework 3.5 that lets you write query-style code.

I'm going to focus on a few things inparticular:

  • When to use it. When not to use it.
  • The performance of LINQ, in terms of speed, when compared to, for example, loops.
  • LINQ over XML and the System.Xml.Linq namespace.

Google Chrome broke my Firefox 3!

After reading about the new Google browser, Google Chrome, I decided to try it out and see for myself how it compared with Firefox and IE.

Initially I was impressed by its clean interface and its homepage feature which displays thumbnails of the websites you use most. It even imported my Firefox bookmarks neatly - although I later found out this process had broken various things in firefox. Let me explain...

The next day, with Firefox still my default browser, I was browsing around (I forgot I had Chrome installed), when I realised that several things in Firefox were behaving strangely. See the screen capture of firefox below:

Firefox broken by Google Chrome

  1. Pretty much the whole of the firefox bookmarks features were now broken and I feared all my bookmarks had been deleted. My firefox bookmarks toolbar was suddenly empty (this had all my RSS feeds on, and my favourite websites) and the bookmarks menu was empty. I'd also lost the ability to add any new bookmarks and couldn't use the "manage bookmarks" feature either. Very annoying.
  2. The address bar was behaving strangely. If I typed "bbc.co.uk", it would normally redirect me to the full address ("http://www.bbc.co.uk/") but now, for some reason, the address bar didn't change, ever, even if I clicked my way off the BBC website and onto another site. It still had "bbc.co.uk" in the address bar, exactly as I typed it.
  3. The icon that indicates that a page is loading was continually telling me it was loading something, even when it had clearly finished loading.

All of this happened straight after I installed Google Chrome Beta, and imported my bookmarks from Firefox. I have now uninstalled Google Chrome permanently, and had to reinstall Firefox to fix what Chrome had broken, and am going to stick to Firefox until I'm sure that Chrome is more stable. Here is a picture of Firefox, reinstalled, and back to it's fully working state:

Firefox fixed again

I'm sure Google Chrome has many advantages - but I'm going to wait a while until I find out what they are!

By the way, I'm posting this complaint using Firefox 3 - go and download it now if you haven't already :-)