OdeToCode IC Logo

More LINQ Optimizations

Thursday, February 12, 2009

Not every optimization is a performance optimization. Imagine trying to get this XML:

string xml = 
    @"<people>
        <Person>
          <property value=""John"" name=""firstName""/>
          <property value=""Dow"" name=""lastName""/>
          <property value=""john@blah.com"" name=""email""/>
        </Person>
        <Person>
          <property value=""Jack"" name=""firstName""/>
          <property value=""Dow"" name=""lastName""/>
          <property value=""jack@blah.com"" name=""email""/>
        </Person>
      </people>";

Into objects of this type:

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
}

A brute force solution would look like the following:

var xmlDoc = XDocument.Parse(xml);
var records =
    from record in xmlDoc.Descendants("Person")
    select new Person
    {
        FirstName = (from p in record.Elements("property") 
                    where p.Attribute("name").Value == "firstName"
                    select p.Attribute("value").Value).FirstOrDefault(),
        LastName = (from p in record.Elements("property") 
                    where p.Attribute("name").Value == "lastName"
                    select p.Attribute("value").Value).FirstOrDefault(),
        Email = (from p in record.Elements("property")
                 where p.Attribute("name").Value == "email"
                 select p.Attribute("value").Value).FirstOrDefault(),

    };

It works - but it’s ugly. It would be better if the code looked like this.

var records =
    from record in xmlDoc.Descendants("Person")
    select new Person
    {
        FirstName = record.Property("firstName"),
        LastName = record.Property("lastName"),
        Email = record.Property("email")
    };

Which just requires a bit of extension method magic.

public static string Property(
    this XElement element, string name)
{
    return
        (from p in element.Elements("property")
         where p.Attribute("name").Value == name
         select p.Attribute("value").Value).FirstOrDefault();
}

Is the code faster? Probably not – but until it’s certain that we have a performance problem, it’s better to optimize for readability.