public static IDiffResult <T> Diff <T, TKey, TData>(
            this IEnumerable <T> previous,
            IEnumerable <T> current,
            Func <T, TKey> keySelector,
            Func <T, TData> dataSelector
            )
        {
            if (keySelector == null)
            {
                throw new ArgumentNullException(nameof(keySelector));
            }

            if (dataSelector == null)
            {
                throw new ArgumentNullException(nameof(dataSelector));
            }

            var diffContext = new DiffContext <T, TKey>(previous, current, keySelector);

            var modifiedKeys   = diffContext.SelectModifiedKeys(dataSelector).ToArray();
            var unmodifiedKeys = diffContext.SelectIntersectingKeys().Except(modifiedKeys).ToArray();

            return(new DiffResult <T>
            {
                Removed = SelectValues(diffContext.Previous, diffContext.SelectRemovedKeys()),
                Added = SelectValues(diffContext.Current, diffContext.SelectAddedKeys()),
                Modified = SelectValues(diffContext.Current, modifiedKeys),
                Unmodified = SelectValues(diffContext.Current, unmodifiedKeys)
            });
        }
        public static IEnumerable <T> SelectAdded <T, TKey>(
            this IEnumerable <T> previous,
            IEnumerable <T> current,
            Func <T, TKey> keySelector
            )
        {
            if (keySelector == null)
            {
                throw new ArgumentNullException(nameof(keySelector));
            }

            var diffContext = new DiffContext <T, TKey>(previous, current, keySelector);

            return(SelectValues(diffContext.Current, diffContext.SelectAddedKeys()));
        }