Mat*_*ore 4 c# collections resharper closures
我实现了这个扩展方法来同步另一个可以是不同类型的集合:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 16
首先让我描述一下Resharper试图提醒您的问题.假设你有:
Action M(Expensive expensive, Cheap cheap)
{
Action shortLived = ()=>{DoSomething(expensive);};
DoSomethingElse(shortLived);
Action longLived = ()=>{DoAnotherThing(cheap);};
return longLived;
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是,在C#(和VB和JScript和许多其他语言)的寿命都 cheap和expensive延伸到的寿命匹配都 shortLived和longLived.所以即使longLived不使用也会发生什么expensive,昂贵的资源在longLived死之前永远不会被垃圾收集.
你的程序符合这种模式; 你用两个lambdas做两个代表; 其中一个使用first,另一个没有.因此first只要两个代表的时间越长,就能生存下去.
第二,让我在这里批评Resharper.这显然是误报.为了使这成为一个真正的积极的一个代表必须长寿.在这种情况下,当方法返回时,两个代表都有资格收集; 两者都是短暂的,因此这里没有实际的错误.Resharper可以跟踪返回的查询对象,Where并注意到它们不能在方法中存活.
第三,你应该怎么做呢?我倾向于什么都不做; 如果代码按照您的喜好工作,那么请继续工作.我不会担心Resharper的警告; 我会更加关注你的代码对于大型集合来说效率极低的事实.如果两个集合具有n和m项,则该程序执行O(nm)操作.
| 归档时间: |
|
| 查看次数: |
1230 次 |
| 最近记录: |