navigation
 Saturday, January 19, 2008

One of the things I have come to love about Linq is how you can focus more on declarative programming: focusing on what you want to accomplish rather than how.

See for example below - I have a generic list of SolutionDescriptor instances (a class in my project that describes a position in a Visual Studio solution), and want to search if for the best match to the language and Visual Studio version preferences in a UserProfile instance:

Note the three queries against the List, each one a Linq expression, starting with an attempt at an exact match, then  match on language preference, and finally one on just version:

private SolutionDescriptor FindBestMatch(List<SolutionDescriptor> startpoints)
{
    UserProfile profile = Singleton<UserProfileManager>.Instance.Profile;

    // first, search for an exact match
    SolutionDescriptor match = (
        from sd in startpoints
        where sd.Language == profile.PreferredLanguage && sd.VSVersion == profile.PreferredVSVersion
        select sd).FirstOrDefault<SolutionDescriptor>();
    if (match == null)
    {
        // next, search by just language
        match = (
            from sd in startpoints
            where sd.Language == profile.PreferredLanguage
            select sd).FirstOrDefault<SolutionDescriptor>();
        if (match == null)
        {
            // finally, search just by VS version
            match = (
                from sd in startpoints
                where sd.VSVersion == profile.PreferredVSVersion
                select sd).FirstOrDefault<SolutionDescriptor>();
        }
    }
    return match;
}

The FirstOrDefault<> method is a way to either get the first match, or the default for the type in question, which is null for my class.