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.


Comments
Raoul Thursday, February 12, 2009
Very nice. Of course I'd want to know why the XML was structured in such a weird way.

I have seen this sort of "lets implement our own schema mechanism on top of something that already has a schema mechanism" approach before and it is seldom a good idea. It is certainly not working with the grain of XML.

The fact that the LINQ/C# toolset is powerful enough to allow us to recover without too many contortions is nice though.
scott Thursday, February 12, 2009
@Raoul:

Agreed. There are some strange XML docs floating around out there. A lot of them are in the healthcare industry :)
Mike Thursday, February 12, 2009
I'd say these types of optimizations (for readability, testability, etc) are more important than speed optimizations, esp if there are no speed problems from the user's perspective.
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!