如何提高foreach循环的性能?

时间:2017-09-15 07:42:28

标签: c# winforms foreach

如何提高 foreach 循环的

foreach (var item in pList)
{
    var foundedItem = source.FirstOrDefault(x => x.LongRecordId == item.LongRecordId);
    if (foundedItem != null && !selectionList.Contains(foundedItem))
    {
        foundedItem.Readonly = pReadonly;
        selectionList.Add(foundedItem);
    }
}

2 个答案:

答案 0 :(得分:4)

如果source以及pList很长,您可以尝试将source转换为Dictionary

 // Provinding that all LongRecordId are distinct
 var dict = source
    .ToDictionary(item => item.LongRecordId, item => item);

 ...

 foreach (var item in pList) {
   MyRecord foundItem = null; //TODO: Put the right type here

   // Instead of O(N) - FirstOrDefault we have O(1) TryGetValue
   if (dict.TryGetValue(item.LongRecordId, out foundItem)) {
     foundItem.Readonly = pReadonly;
     selectionList.Add(foundItem);
   } 
 }

修改:如果您想确保selectionList仅包含不同的项目(请参阅Ferhat Sayan的评论),请尝试HashSet

 ...

 HashSet<MyRecord> selectedHash = new HashSet<MyRecord>(selectionList);

 foreach (var item in pList) {
   MyRecord foundItem null; //TODO: Put the right type here

   // Instead of O(N) - FirstOrDefault we have O(1) TryGetValue
   if (dict.TryGetValue(item.LongRecordId, out foundItem)) {
     foundItem.Readonly = pReadonly;
     selectedHash.Add(foundItem);
   } 
 }

 selectionList = selectedHash.ToList();

答案 1 :(得分:2)

我建议对这段代码进行分析。

我想最耗时的电话是FirstOrDefault-Extension方法。

如果有任何性能提升,使用而不是foreach不太可能给你很多。

很可能你的问题源于你的上下文变量,可能是一个非常大的源列表?

总的来说,此代码部分可能不是寻找性能改进的最佳位置。如果这是唯一的地方,你应该考虑重新设计。

如果您有非常大的列表并且不担心并发问题,那么您可以使用并行或多处理路由。 parallel.foreach是进行某些测试的便宜方式。

使用Dictionary而不是List应该可以加快速度。如果您使用HashSet(以产生uniqunes的好处),请注意实现正确的IEqualityComparer,或者当您添加依赖于DefaultComparer的大量项目时甚至可以lose performance