Q:

Using LINQ to get the difference between two list of objects based only on a single object property

the dog class has two properties (name and color)
Let's say I have two IEnumerable lists:
List1 [{name="Sam", color="Fawn"}, {name="Mary", color=""}, {name="Bob", color=""}]
List2 [{name="Mary", color="Black"},{name="Bob", color="Yellow"}]

I want to get a list of dog objects that differ ONLY in name
so my return list would look like
ListReturn: [{name="Sam", color="Fawn"}]

Make Sense?
I want to do this with linq. This is what I've tried... and it's not working
any help?
  var missing = from l1 in List1
                join l2 in List2 on l1.Name equals l2.Name into merged
                from missed in merged.DefaultIfEmpty()
                select missed;

I may be a complete moron, but I've stared at this all day and can't get it. any help would be appreciated.

A:

What you have is functionally Except, but instead of using equality of the whole item, you want to perform the Except using a selected property as the key.  While you could provide a custom IEqualityComparer to Except that only compared names, writing that comparer is a fair bit of error prone boilerplate code.  We can write a method that performs an Except on a projected key fairly easily:
public static IEnumerable<TSource> ExceptBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    IEnumerable<TSource> other,
    Func<TSource, TKey> keySelector)
{
    var set = new HashSet<TKey>(other.Select(keySelector));
    foreach(var item in source)
        if(set.Add(keySelector(item)))
            yield return item;
}

This performs an except using the given key, instead of a custom equality comparer.
Now your query is simply:
var query = list1.ExceptBy(list2, dog => dog.name);

