Loading... Loading latest track...

In my last post I found out that you can bind anonymous types to repeaters in C#, but there's a lot of other interesting things you can do with anonymous types, such as performing a LINQ Union operation on two anonymous type collections. I'll show how this is possible using a simple example.

Firstly, let's say that you have created a web application where people can use their existing facebook or twitter account to log on to your website. In a slightly naive example we will first get a list of users from facebook, and another list from twitter, and join them together into one user list and then work with them.

XDocument facebookXml = GetFacebookUsers();

var facebookQuery = from user in facebookXml.Descendants("FacebookUser")
select new
{
Username = (string) user.Element("Username"),
Firstname = (string) user.Element("Firstname"),
Lastname = (string) user.Element("Lastname"),
Birthday = (DateTime) user.Element("Birthday"),
Country = (string) user.Element("CountryName")
};

XDocument twitterXml = GetTwitterUsers();

var twitterQuery = from user in twitterXml.Descendants("TwitterUser")
select new
{
Username = (string) user.Element("Username"),
Firstname = (string) user.Element("Firstname"),
Lastname = (string) user.Element("Lastname"),
Birthday = (DateTime) user.Element("DOB"),
Country = (string) user.Element("Country")
};

On a side note, I'm casting the inner XElement objects to string, or DateTime; I prefer doing this to user.Element("Username").Value due to the fact that the end result is the same but we avoid the NullReferenceException that .Value may give us.

Although the two XML document's come from different sources and in fact have different structures and element names, the key thing here is that the anonymous type I have created in the facebookQuery has the same property names (and types) as the anonymous type I create in the second query (the twitterQuery). The .NET compiler is clever enough to realise that these two anonymous types are not two distinct anonymous types with the same properties, but are in fact the same anonymous type. The LINQ union set operator can obviously only be used on sets/collections of the same type, but that is exactly what we want to do next (the only difference being that we are allowing the compiler to create the type for us). Here is what we would want to do next:

var allUsers = facebookQuery.Union(twitterQuery);

Or most likely a more useful query like the one below:

var allUsers = facebookQuery.Union(twitterQuery)
.Distinct()
.Where(u => u.Country == "Norway");

One thing to note is if we add another property to the first anonymous type, for example a new string property called MobileNumber, the anonymous types will now be different (i.e. they will be two distinct anonymous types) and we will not be able to use the LINQ Union operation any longer:

var facebookQuery = from user in facebookXml.Descendants("FacebookUser")
select new
{
Username = (string) user.Element("Username"),
Firstname = (string) user.Element("Firstname"),
Lastname = (string) user.Element("Lastname"),
Birthday = (DateTime) user.Element("Birthday"),
Country = (string) user.Element("CountryName"),
MobileNumber = (string) user.Element("Mobile")
};

var twitterQuery = from user in twitterXml.Descendants("TwitterUser")
select new
{
Username = (string) user.Element("Username"),
Firstname = (string) user.Element("Firstname"),
Lastname = (string) user.Element("Lastname"),
Birthday = (DateTime) user.Element("DOB"),
Country = (string) user.Element("Country")
};

// This will result in a compile time error
var allUsers = facebookQuery.Union(twitterQuery);

DataBinding with Anonymous Types in C#

I wanted to use an ASP.NET repeater to bind some data to a web form, but the data in the code came from two different places. I used LINQ to join my two data collections together, but the problem was that this resulted in my query returning an IEnumerable of anonymous types. I thought that this would mean I'm not going to be able to bind these anonymous type objects to my repeater without creating a strongly typed class or struct.

It turns out that I was wrong: I can bind anonymous types to a repeater! That's pretty cool, and I'll show you how I did it. My LINQ query looked like this:

Customer[] customers = GetCustomers();
Country[] countries = GetCountries();

var query = from customer in customers
            join country in countries on customer.CountryID equals country.CountryID
            where customer.Age > 21 &&
                  country.Name == "United Kingdom"
            select new
                       {
                           CustomerName = customer.Name,
                           CountryName = country.Name
                       };

MyRepeater.DataSource = query.ToArray();
MyRepeater.DataBind();

As you can see, I'm using CustomerName from one type of object, and CountryName from another type, and joining these together into a new anonymous type.

After this, in my HTML/ASCX I can use a repeater like this:

<asp:Repeater ID="MyRepeater" runat="server">
    <ItemTemplate>
        <p>
            <%# Eval("CustomerName") %>
            lives in
            <%# Eval("CountryName") %>
        </p>
    </ItemTemplate>
</asp:Repeater>

When you think about it, this actually makes sense. Anonymous types of course are real types - it's just that the compiler generates the type for me, so I don't have to.

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.