I use the following code to get the changes between two collections. Objects are joined using a primary key. Any tips on performance issues or other optimizations appreciated./// <summary>/// Gets the changes [Deleted, changed, inserted] comparing this collection to another./// </summary>/// <param name=local>The source collection.</param>/// <param name=remote>The remote collection to comare agains.</param>/// <param name=keySelector>The primary key selector function</param>/// <returns></returns>public static ChangeResult<TSource> CompareTo<TSource, TKey>(this IEnumerable<TSource> local, IEnumerable<TSource> remote, Func<TSource, TKey> keySelector){    if (local == null)        throw new ArgumentNullException(local);    if (remote == null)        throw new ArgumentNullException(remote);    if (keySelector == null)        throw new ArgumentNullException(keySelector);    var remoteKeyValues = remote.ToDictionary(keySelector);    var deleted = new List<TSource>();    var changed = new List<TSource>();    var localKeys = new HashSet<TKey>();    foreach (var localItem in local)    {        var localKey = keySelector(localItem);        localKeys.Add(localKey);        /* Check if primary key exists in both local and remote          * and if so check if changed, if not it has been deleted         */        TSource changeCandidate;        if (remoteKeyValues.TryGetValue(localKey, out changeCandidate))        {            if (!changeCandidate.Equals(localItem))                changed.Add(changeCandidate);        }        else        {            deleted.Add(localItem);        }    }    var inserted = remoteKeyValues                    .Where(x => !localKeys.Contains(x.Key))                    .Select(x => x.Value)                    .ToList();    return new ChangeResult<TSource>(deleted, changed, inserted);}/// <summary>/// Immutable class containing changes/// </summary>public class ChangeResult<T>{    public ChangeResult(IList<T> deleted, IList<T> changed, IList<T> inserted)    {        Deleted = new ReadOnlyCollection<T>(deleted);        Changed = new ReadOnlyCollection<T>(changed);        Inserted = new ReadOnlyCollection<T>(inserted);    }    public IList<T> Deleted { get; private set; }    public IList<T> Changed { get; private set; }    public IList<T> Inserted { get; private set; }}Usagevar changes = Col1.CompareTo(Col2, x => x.UniqueId);
Optimization of comparing two collections and get the changes
c#;.net
I think it looks like good, clear, general purpose code. I don't see any really significant changes to make, but there might be some minor improvements available.First, allocating default size collections and letting them grow naturally may not work well for large collections. IIRC they start at 10 elements, and then double each time they top out. But each doubling requires a reallocation and a copy, which can add up when you're adding thousands of items. You should initialize them with the proper size if you know what it is. If you can take a decent guess, even that will help: starting at (for example) 200 elements instead of 10 will save you a lot of allocations. But avoid calling Count() on your input IEnumerable objects since that could cause them to be enumerated an extra time, depending on the underlying implementation.Second, if you commonly have no insertions in remote and no deletions in local, you could add some code to skip the final enumeration of remoteKeyValue. As you're enumerating local, keep a count of how many items were found in remoteKeyValues. If the number you end up with is equal to remoteKeyValues.Count then you know there are no insertions, because you already matched all the items in that collection.As always with performance tweaking, profile it before and after any changes.