我实现了这个扩展方法来同步另一个可以是不同类型的集合:
public static void Synchronize<TFirst, TSecond>(
this ICollection<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, bool> match,
Func<TSecond, TFirst> create)
{
var secondCollection = second.ToArray();
var toAdd = secondCollection.Where(item => !first.Any(x => match(x, item))).Select(create);
foreach (var item in toAdd)
{
first.Add(item);
}
var toRemove = first.Where(item => !secondCollection.Any(x => match(item, x))).ToArray();
foreach (var item in toRemove)
{
first.Remove(item);
}
}
ReSharper 给了我两个“隐式捕获的闭包”,一个在第一个 Where 和一个在第二个,有没有办法解决它?我找不到一个。
[更新]
根据 Eric 的观察,我编写了一个比使用 equals 函数更快的版本,而是使用哈希:
public static void Synchronize<TFirst, TSecond>(
this ICollection<TFirst> first,
IEnumerable<TSecond> second,
Func<TSecond, TFirst> convert,
Func<TFirst, int> firstHash = null,
Func<TSecond, int> secondHash = null)
{
if (firstHash == null)
{
firstHash = x => x.GetHashCode();
}
if (secondHash == null)
{
secondHash = x => x.GetHashCode();
}
var firstCollection = first.ToDictionary(x => firstHash(x), x => x);
var secondCollection = second.ToDictionary(x => secondHash(x), x => x);
var toAdd = secondCollection.Where(item => firstCollection.All(x => x.Key != item.Key)).Select(x => convert(x.Value));
foreach (var item in toAdd)
{
first.Add(item);
}
var toRemove = firstCollection.Where(item => secondCollection.All(x => x.Key != item.Key));
foreach (var item in toRemove)
{
first.Remove(item.Value);
}
}