using System.Collections.Generic;
public static class Extensions
public static void Write<K, V>(this IEnumerable<KeyValuePair<K, V>> me, string label)
Console.WriteLine($"---- {label} ----");
Console.WriteLine($"[{kvp.Key}]={kvp.Value}");
public static IEnumerable<KeyValuePair<K, V>> ToDictionaryNoDups<K, V>(this IEnumerable<V> me, Func<V, K> selector) where K : notnull
Dictionary<K, V> dictionary = new();
K key = selector.Invoke(v);
if(dictionary.ContainsKey(key))
public string Name { get; set; }
public string Value { get; set; }
public class WidgetComparer : IEqualityComparer<KeyValuePair<string, Widget>>
private StringComparer _stringComparer;
public WidgetComparer(StringComparer stringComparer = null)
_stringComparer = stringComparer ?? StringComparer.InvariantCultureIgnoreCase;
public bool Equals(KeyValuePair<string, Widget> me, KeyValuePair<string, Widget> other)
return _stringComparer.Compare(me.Key, other.Key) == 0;
public int GetHashCode(KeyValuePair<string, Widget> me)
return HashCode.Combine(me.Key.GetHashCode());
public readonly static IEqualityComparer<KeyValuePair<string, Widget>> WidgetComparerInvariantCulture = new WidgetComparer(StringComparer.InvariantCulture);
public readonly static IEqualityComparer<KeyValuePair<string, Widget>> WidgetComparerInvariantCultureIgnoreCase = new WidgetComparer(StringComparer.InvariantCultureIgnoreCase);
public static void Main()
Widget[] widgets1 = new Widget[] {
new() { Name = "a", Value = "A1" },
new() { Name = "b", Value = "B1" },
new() { Name = "a", Value = "AA1" }
Widget[] widgets2 = new Widget[] {
new() { Name = "b", Value = "B2" },
new() { Name = "c", Value = "C2" },
new() { Name = "d", Value = "D2" }
Dictionary<string, Widget> v1 = new(widgets1.ToDictionaryNoDups(x => x.Name));
Dictionary<string, Widget> v2 = new(widgets2.ToDictionaryNoDups(x => x.Name));
Dictionary<string, Widget> all = new(v1.Union(v2).Select(x => x.Value).ToDictionaryNoDups(x => x.Name));
all.Write("all - no dups");
all.Except(v1, WidgetComparer.WidgetComparerInvariantCultureIgnoreCase).Write("all except v1");
all.Except(v2, WidgetComparer.WidgetComparerInvariantCultureIgnoreCase).Write("all except v2");
v1.Union(v2, WidgetComparer.WidgetComparerInvariantCultureIgnoreCase).Write("widgets1 union widgets2");