Skip to content

Instantly share code, notes, and snippets.

@glenndierckx
Last active October 2, 2025 07:24
Show Gist options
  • Select an option

  • Save glenndierckx/53a22f54ab76ccfb79ad to your computer and use it in GitHub Desktop.

Select an option

Save glenndierckx/53a22f54ab76ccfb79ad to your computer and use it in GitHub Desktop.
namespace Shared.Helpers;
public static class MergeHelper
{
public static void Merge<TCurrent, TToBe, TId>(
this IEnumerable<TCurrent> current,
IEnumerable<TToBe> toBe,
Func<TCurrent, TId> currentIdSelector,
Func<TToBe, TId> toBeIdSelector,
Action<TToBe>? onAdd = null,
Action<TCurrent, TToBe>? onUpdate = null,
Action<TCurrent>? onRemove = null)
{
var currentList = current.ToList();
var toBeList = toBe.ToList();
var leftOuterJoin = currentList.GroupJoin(toBeList,
currentIdSelector,
toBeIdSelector,
(currentEntity, toBeEntity) => new
{
currentEntity = (object?)currentEntity,
toBeEntity = (object?)toBeEntity.DefaultIfEmpty().SingleOrDefault()
});
var rightOuterJoin = toBeList.GroupJoin(currentList,
toBeIdSelector,
currentIdSelector,
(toBeEntity, currentEntity) => new
{
currentEntity = (object?)currentEntity.DefaultIfEmpty().SingleOrDefault(),
toBeEntity = (object?)toBeEntity
});
var fullOuterJoin = leftOuterJoin.Union(rightOuterJoin).ToArray();
foreach (var entity in fullOuterJoin)
{
if (entity.toBeEntity is null && entity.currentEntity is not null)
{
onRemove?.Invoke((TCurrent)entity.currentEntity);
}
else if (entity.currentEntity is null && entity.toBeEntity is not null)
{
onAdd?.Invoke((TToBe)entity.toBeEntity);
}
else if (entity.currentEntity is not null && entity.toBeEntity is not null)
{
onUpdate?.Invoke((TCurrent)entity.currentEntity, (TToBe)entity.toBeEntity);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment